nodal-agents 0.3.9 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/README.md +7 -7
  2. package/cli.js +73 -2
  3. package/migrations/0023_agent_schedules_notify_on_success.sql +10 -0
  4. package/migrations/0024_agent_jobs_dashboard_channel.sql +11 -0
  5. package/migrations/0025_agent_jobs_conversational.sql +9 -0
  6. package/migrations/0026_chat_messages.sql +19 -0
  7. package/migrations/0027_drop_agent_jobs_conversational.sql +6 -0
  8. package/migrations/0028_conversations.sql +27 -0
  9. package/migrations/0029_backfill_root_agent.sql +33 -0
  10. package/migrations/meta/_journal.json +216 -167
  11. package/package.json +1 -1
  12. package/runner.js +1858 -1194
  13. package/web/.next/BUILD_ID +1 -1
  14. package/web/.next/app-path-routes-manifest.json +1 -0
  15. package/web/.next/build-manifest.json +2 -2
  16. package/web/.next/routes-manifest.json +6 -0
  17. package/web/.next/server/app/(dashboard)/agents/[id]/edit/page.js +3 -3
  18. package/web/.next/server/app/(dashboard)/agents/[id]/edit/page.js.nft.json +1 -1
  19. package/web/.next/server/app/(dashboard)/agents/[id]/edit/page_client-reference-manifest.js +1 -1
  20. package/web/.next/server/app/(dashboard)/agents/[id]/telegram/page.js +2 -2
  21. package/web/.next/server/app/(dashboard)/agents/[id]/telegram/page.js.nft.json +1 -1
  22. package/web/.next/server/app/(dashboard)/agents/[id]/telegram/page_client-reference-manifest.js +1 -1
  23. package/web/.next/server/app/(dashboard)/agents/page.js +2 -2
  24. package/web/.next/server/app/(dashboard)/agents/page.js.nft.json +1 -1
  25. package/web/.next/server/app/(dashboard)/agents/page_client-reference-manifest.js +1 -1
  26. package/web/.next/server/app/(dashboard)/approvals/page.js +2 -2
  27. package/web/.next/server/app/(dashboard)/approvals/page.js.nft.json +1 -1
  28. package/web/.next/server/app/(dashboard)/approvals/page_client-reference-manifest.js +1 -1
  29. package/web/.next/server/app/(dashboard)/automations/page.js +2 -2
  30. package/web/.next/server/app/(dashboard)/automations/page.js.nft.json +1 -1
  31. package/web/.next/server/app/(dashboard)/automations/page_client-reference-manifest.js +1 -1
  32. package/web/.next/server/app/(dashboard)/billing/page.js +2 -2
  33. package/web/.next/server/app/(dashboard)/billing/page.js.nft.json +1 -1
  34. package/web/.next/server/app/(dashboard)/billing/page_client-reference-manifest.js +1 -1
  35. package/web/.next/server/app/(dashboard)/chat/page.js +2 -0
  36. package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -0
  37. package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -0
  38. package/web/.next/server/app/(dashboard)/connectors/page.js +2 -2
  39. package/web/.next/server/app/(dashboard)/connectors/page.js.nft.json +1 -1
  40. package/web/.next/server/app/(dashboard)/connectors/page_client-reference-manifest.js +1 -1
  41. package/web/.next/server/app/(dashboard)/credentials/page.js +2 -2
  42. package/web/.next/server/app/(dashboard)/credentials/page.js.nft.json +1 -1
  43. package/web/.next/server/app/(dashboard)/credentials/page_client-reference-manifest.js +1 -1
  44. package/web/.next/server/app/(dashboard)/jobs/[id]/page.js +2 -2
  45. package/web/.next/server/app/(dashboard)/jobs/[id]/page.js.nft.json +1 -1
  46. package/web/.next/server/app/(dashboard)/jobs/[id]/page_client-reference-manifest.js +1 -1
  47. package/web/.next/server/app/(dashboard)/jobs/page.js +2 -2
  48. package/web/.next/server/app/(dashboard)/jobs/page.js.nft.json +1 -1
  49. package/web/.next/server/app/(dashboard)/jobs/page_client-reference-manifest.js +1 -1
  50. package/web/.next/server/app/(dashboard)/llm-providers/page.js +2 -2
  51. package/web/.next/server/app/(dashboard)/llm-providers/page.js.nft.json +1 -1
  52. package/web/.next/server/app/(dashboard)/llm-providers/page_client-reference-manifest.js +1 -1
  53. package/web/.next/server/app/(dashboard)/logs/page.js +2 -2
  54. package/web/.next/server/app/(dashboard)/logs/page.js.nft.json +1 -1
  55. package/web/.next/server/app/(dashboard)/logs/page_client-reference-manifest.js +1 -1
  56. package/web/.next/server/app/(dashboard)/mcp/page.js +2 -2
  57. package/web/.next/server/app/(dashboard)/mcp/page.js.nft.json +1 -1
  58. package/web/.next/server/app/(dashboard)/mcp/page_client-reference-manifest.js +1 -1
  59. package/web/.next/server/app/(dashboard)/memories/page.js +2 -2
  60. package/web/.next/server/app/(dashboard)/memories/page.js.nft.json +1 -1
  61. package/web/.next/server/app/(dashboard)/memories/page_client-reference-manifest.js +1 -1
  62. package/web/.next/server/app/(dashboard)/page.js +3 -3
  63. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  64. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  65. package/web/.next/server/app/(dashboard)/settings/page.js +2 -63
  66. package/web/.next/server/app/(dashboard)/settings/page.js.nft.json +1 -1
  67. package/web/.next/server/app/(dashboard)/settings/page_client-reference-manifest.js +1 -1
  68. package/web/.next/server/app/(dashboard)/skills/[id]/edit/page.js +2 -2
  69. package/web/.next/server/app/(dashboard)/skills/[id]/edit/page.js.nft.json +1 -1
  70. package/web/.next/server/app/(dashboard)/skills/[id]/edit/page_client-reference-manifest.js +1 -1
  71. package/web/.next/server/app/(dashboard)/skills/new/page.js +2 -2
  72. package/web/.next/server/app/(dashboard)/skills/new/page.js.nft.json +1 -1
  73. package/web/.next/server/app/(dashboard)/skills/new/page_client-reference-manifest.js +1 -1
  74. package/web/.next/server/app/(dashboard)/skills/page.js +2 -2
  75. package/web/.next/server/app/(dashboard)/skills/page.js.nft.json +1 -1
  76. package/web/.next/server/app/(dashboard)/skills/page_client-reference-manifest.js +1 -1
  77. package/web/.next/server/app/_global-error/page.js +2 -2
  78. package/web/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  79. package/web/.next/server/app/_global-error.html +1 -1
  80. package/web/.next/server/app/_global-error.rsc +1 -1
  81. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  82. package/web/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  83. package/web/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  84. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  85. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  86. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  87. package/web/.next/server/app/_not-found/page.js +2 -2
  88. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  89. package/web/.next/server/app/_not-found.html +1 -1
  90. package/web/.next/server/app/_not-found.rsc +2 -2
  91. package/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  92. package/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  93. package/web/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  94. package/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  95. package/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  96. package/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  97. package/web/.next/server/app/api/auth/[...all]/route.js +1 -1
  98. package/web/.next/server/app/api/health/route.js +1 -1
  99. package/web/.next/server/app/api/oauth/[provider]/callback/route.js +1 -1
  100. package/web/.next/server/app/api/oauth/[provider]/start/route.js +1 -1
  101. package/web/.next/server/app/auth/callback/route.js +1 -1
  102. package/web/.next/server/app/login/page.js +2 -2
  103. package/web/.next/server/app/login/page_client-reference-manifest.js +1 -1
  104. package/web/.next/server/app/onboarding/page.js +2 -2
  105. package/web/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
  106. package/web/.next/server/app/onboarding.html +1 -1
  107. package/web/.next/server/app/onboarding.rsc +2 -2
  108. package/web/.next/server/app/onboarding.segments/_full.segment.rsc +2 -2
  109. package/web/.next/server/app/onboarding.segments/_head.segment.rsc +1 -1
  110. package/web/.next/server/app/onboarding.segments/_index.segment.rsc +2 -2
  111. package/web/.next/server/app/onboarding.segments/_tree.segment.rsc +2 -2
  112. package/web/.next/server/app/onboarding.segments/onboarding/__PAGE__.segment.rsc +1 -1
  113. package/web/.next/server/app/onboarding.segments/onboarding.segment.rsc +1 -1
  114. package/web/.next/server/app-paths-manifest.json +1 -0
  115. package/web/.next/server/chunks/1511.js +1 -0
  116. package/web/.next/server/chunks/2103.js +1 -0
  117. package/web/.next/server/chunks/{6937.js → 3057.js} +1 -1
  118. package/web/.next/server/chunks/4574.js +1 -1
  119. package/web/.next/server/chunks/7557.js +62 -0
  120. package/web/.next/server/chunks/7741.js +15 -15
  121. package/web/.next/server/chunks/8178.js +1 -0
  122. package/web/.next/server/chunks/9201.js +1 -0
  123. package/web/.next/server/chunks/9824.js +1 -0
  124. package/web/.next/server/middleware-build-manifest.js +1 -1
  125. package/web/.next/server/pages/404.html +1 -1
  126. package/web/.next/server/pages/500.html +1 -1
  127. package/web/.next/server/server-reference-manifest.js +1 -1
  128. package/web/.next/server/server-reference-manifest.json +1 -1
  129. package/web/.next/static/9FXcaPSw8KYgjKzjKLpT2/_buildManifest.js +1 -0
  130. package/web/.next/static/chunks/2569-6b5e0af9c1f584a4.js +1 -0
  131. package/web/.next/static/chunks/5801-e411029984b17b8b.js +1 -0
  132. package/web/.next/static/chunks/8503-ced632da5c3fce79.js +1 -0
  133. package/web/.next/static/chunks/9421-d522a48618c4fe37.js +62 -0
  134. package/web/.next/static/chunks/app/(dashboard)/automations/page-4807e81e2af3030e.js +1 -0
  135. package/web/.next/static/chunks/app/(dashboard)/chat/page-2c8f9571a443f250.js +1 -0
  136. package/web/.next/static/chunks/app/(dashboard)/connectors/page-72ccb0e3a5ed6f2d.js +1 -0
  137. package/web/.next/static/chunks/app/(dashboard)/layout-4d5634ba460464d7.js +1 -0
  138. package/web/.next/static/chunks/app/(dashboard)/mcp/page-426478332dfe8313.js +1 -0
  139. package/web/.next/static/chunks/app/(dashboard)/settings/page-1cc10beb46234c7d.js +1 -0
  140. package/web/.next/static/chunks/app/(dashboard)/skills/[id]/edit/{page-5fab5bdd950d7037.js → page-0b61f21847f4c7a0.js} +1 -1
  141. package/web/.next/static/chunks/app/(dashboard)/skills/new/{page-86cfe805e82b43aa.js → page-9de96e643c361732.js} +1 -1
  142. package/web/.next/static/chunks/app/(dashboard)/skills/page-4566512d74e54bfe.js +1 -0
  143. package/web/.next/static/css/0a81480f93d3ab37.css +3 -0
  144. package/web/.next/server/chunks/1248.js +0 -1
  145. package/web/.next/server/chunks/3362.js +0 -1
  146. package/web/.next/server/chunks/5527.js +0 -1
  147. package/web/.next/server/chunks/8193.js +0 -1
  148. package/web/.next/static/8MmUGL73Wv8U4wr-eDBt8/_buildManifest.js +0 -1
  149. package/web/.next/static/chunks/374-60415230f01c844a.js +0 -1
  150. package/web/.next/static/chunks/5070-4385fb454f6ec84b.js +0 -62
  151. package/web/.next/static/chunks/639-79c3c2ac769ef007.js +0 -1
  152. package/web/.next/static/chunks/app/(dashboard)/automations/page-70005fabd08ae4a5.js +0 -1
  153. package/web/.next/static/chunks/app/(dashboard)/connectors/page-e12174534c2c2acf.js +0 -1
  154. package/web/.next/static/chunks/app/(dashboard)/layout-d01f5919f54fb37a.js +0 -1
  155. package/web/.next/static/chunks/app/(dashboard)/mcp/page-3fa9d4448a31b696.js +0 -1
  156. package/web/.next/static/chunks/app/(dashboard)/settings/page-550fcfa4184838ea.js +0 -1
  157. package/web/.next/static/chunks/app/(dashboard)/skills/page-54c6adeb65475a1a.js +0 -1
  158. package/web/.next/static/css/e7183ce0b0791ec7.css +0 -3
  159. /package/web/.next/static/{8MmUGL73Wv8U4wr-eDBt8 → 9FXcaPSw8KYgjKzjKLpT2}/_ssgManifest.js +0 -0
package/README.md CHANGED
@@ -204,7 +204,7 @@ pnpm deps:check # runs locally and in CI before every release
204
204
 
205
205
  ## Status
206
206
 
207
- **Current release:** `0.3.9` on npm `latest`. Used daily by the
207
+ **Current release:** `0.3.10` on npm `latest`. Used daily by the
208
208
  maintainer, stable enough for personal production. Pre-1.0 — breaking
209
209
  changes are still possible between minors.
210
210
 
@@ -220,15 +220,16 @@ changes are still possible between minors.
220
220
  Airtable) and API-key (Notion, Airtable, Apify, Firecrawl, Tavily)
221
221
  - MCP catalog — Streamable HTTP *and* stdio (local subprocess) servers, API-key auth; a growing catalogue (Stripe, n8n, Supabase, Airtable, Notion…) with a "test pending" badge on entries not yet verified live, plus add *and edit* your own custom HTTP/stdio servers from the dashboard
222
222
  - Top-level workspaces — multiple isolated entities (agents/skills/connectors/jobs/memory per workspace), switch in the sidebar
223
- - ROOT agentdesignate an orchestrator that can create skills/agents and assign them, gated by per-grant toggles + an autonomy/approval level
223
+ - In-app ROOT chattalk to your workspace ROOT right in the dashboard: conversation-first (pure chat never creates a job — recall is free, the agent's memory is auto-loaded), multiple conversations with searchable history, and inline "dispatched to N agents" cards when it escalates a real action into a tracked job
224
+ - ROOT agent — your first orchestrator automatically becomes the workspace ROOT (the single top-level agent; later orchestrators slot under it). It can create *and update* skills, create agents and assign them, and create MCP servers + API connectors — each gated by per-grant toggles + an autonomy/approval level (powers start off, opt in per grant). Provisioning verifies before it writes (an MCP server is connected and its tools listed first); skill authoring is grounded in the workspace's real tools (a linter rejects skills referencing tools the agent doesn't have)
224
225
  - Office file editing — Excel in-place edit, Word/PowerPoint create, in the agent workspace (office-editing skill)
225
226
  - Multiple filesystem folders per agent (sandboxed `file_*` tools)
226
227
  - Telegram delivery (long-poll, group filters, multi-agent routing,
227
228
  delegation gracefulness) — exactly-once delivery contract: anti-spam guard
228
229
  against runaway message loops + a guard that re-prompts (then fails loud)
229
230
  rather than completing a job without ever replying
230
- - Approval gates for risky tools (execute-the-approved-action on resume)
231
- - Cron scheduling
231
+ - Approval gates for risky tools (execute-the-approved-action on resume) — on a chat channel, the agent sends a heads-up before the job pauses so the user knows an approval is waiting
232
+ - Cron scheduling — trigger any automation out-of-band ("Run now") + opt-in Telegram confirmation when a scheduled job succeeds
232
233
  - `nodal-agents update` — one-command upgrade + boot version notice
233
234
  - Encryption at rest for LLM keys + MCP keys
234
235
  - Embedded Postgres distribution via npm (no external DB to install)
@@ -237,9 +238,8 @@ changes are still possible between minors.
237
238
 
238
239
  - **MCP OAuth flow** → unlocks Linear, Notion remote, GitHub remote,
239
240
  Atlassian, Sentry, and the rest of the SaaS-as-MCP ecosystem.
240
- - **Dashboard chat for the ROOT companion** → talk to your ROOT agent in
241
- the app, multi-turn, instead of via Telegram; plus a dry-run mode and a
242
- test-workflow meta-tool.
241
+ - **Dry-run mode + a test-workflow meta-tool** → preview what the ROOT would
242
+ do before it runs, and let it validate an automation end-to-end.
243
243
  - **pgvector binaries bundled in the npm pack** → semantic memory search
244
244
  active out-of-the-box. Today, installs without pgvector fall back to
245
245
  keyword search (which works, just less smart for cross-vocabulary
package/cli.js CHANGED
@@ -11272,7 +11272,8 @@ var init_enums = __esm({
11272
11272
  "cron",
11273
11273
  "task-board",
11274
11274
  "slack",
11275
- "discord"
11275
+ "discord",
11276
+ "dashboard"
11276
11277
  ];
11277
11278
  JobChannelSchema = z2.enum(JOB_CHANNELS);
11278
11279
  JOB_STATUSES = [
@@ -12168,12 +12169,22 @@ var init_root_agent = __esm({
12168
12169
  RootGrantsSchema = z19.object({
12169
12170
  createAgent: z19.boolean(),
12170
12171
  createSkill: z19.boolean(),
12172
+ updateSkill: z19.boolean(),
12171
12173
  assignSkill: z19.boolean(),
12174
+ createMcp: z19.boolean(),
12175
+ createConnector: z19.boolean(),
12172
12176
  autonomy: AutonomyLevelSchema
12173
12177
  });
12174
12178
  }
12175
12179
  });
12176
12180
 
12181
+ // ../../packages/shared/src/connector-catalog.ts
12182
+ var init_connector_catalog = __esm({
12183
+ "../../packages/shared/src/connector-catalog.ts"() {
12184
+ "use strict";
12185
+ }
12186
+ });
12187
+
12177
12188
  // ../../packages/shared/src/index.ts
12178
12189
  var init_src2 = __esm({
12179
12190
  "../../packages/shared/src/index.ts"() {
@@ -12198,6 +12209,7 @@ var init_src2 = __esm({
12198
12209
  init_operation();
12199
12210
  init_providers();
12200
12211
  init_root_agent();
12212
+ init_connector_catalog();
12201
12213
  }
12202
12214
  });
12203
12215
 
@@ -12530,7 +12542,7 @@ var init_jobs = __esm({
12530
12542
  ),
12531
12543
  check(
12532
12544
  "agent_jobs_channel_check",
12533
- sql`${table.channel} IN ('telegram','api','whatsapp','internal','cron','task-board','slack','discord')`
12545
+ sql`${table.channel} IN ('telegram','api','whatsapp','internal','cron','task-board','slack','discord','dashboard')`
12534
12546
  )
12535
12547
  ]
12536
12548
  );
@@ -12975,6 +12987,10 @@ var init_schedules = __esm({
12975
12987
  nextRun: timestamp("next_run", { withTimezone: true }),
12976
12988
  lastStatus: text("last_status"),
12977
12989
  chatId: text("chat_id"),
12990
+ // Opt-in: when true, a fired job carries a delivery target so the runner
12991
+ // forces the agent to send the user a success confirmation before finishing.
12992
+ // Default false → the cron runs silently (the user must opt in per schedule).
12993
+ notifyOnSuccess: boolean("notify_on_success").notNull().default(false),
12978
12994
  createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
12979
12995
  updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow()
12980
12996
  },
@@ -13285,6 +13301,56 @@ var init_agent_workspaces = __esm({
13285
13301
  }
13286
13302
  });
13287
13303
 
13304
+ // ../../packages/db/src/schema/chat-messages.ts
13305
+ var conversations, chatMessages;
13306
+ var init_chat_messages = __esm({
13307
+ "../../packages/db/src/schema/chat-messages.ts"() {
13308
+ "use strict";
13309
+ init_pg_core();
13310
+ init_drizzle_orm();
13311
+ init_entities();
13312
+ init_agents();
13313
+ init_jobs();
13314
+ conversations = pgTable(
13315
+ "conversations",
13316
+ {
13317
+ id: uuid("id").primaryKey().defaultRandom(),
13318
+ entityId: uuid("entity_id").references(() => entities.id, { onDelete: "cascade" }),
13319
+ // The agent this conversation is with (the ROOT, today).
13320
+ agentId: uuid("agent_id").notNull().references(() => agents.id, { onDelete: "cascade" }),
13321
+ title: text("title").notNull().default(""),
13322
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow(),
13323
+ // Bumped on each new turn — drives the recency sort in the sidebar.
13324
+ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow()
13325
+ },
13326
+ (table) => [
13327
+ index("idx_conversations_entity_agent").on(table.entityId, table.agentId, table.updatedAt)
13328
+ ]
13329
+ );
13330
+ chatMessages = pgTable(
13331
+ "chat_messages",
13332
+ {
13333
+ id: uuid("id").primaryKey().defaultRandom(),
13334
+ entityId: uuid("entity_id").references(() => entities.id, { onDelete: "cascade" }),
13335
+ agentId: uuid("agent_id").notNull().references(() => agents.id, { onDelete: "cascade" }),
13336
+ conversationId: uuid("conversation_id").references(() => conversations.id, {
13337
+ onDelete: "cascade"
13338
+ }),
13339
+ role: text("role").notNull(),
13340
+ content: text("content").notNull(),
13341
+ // Set when this (assistant) turn escalated into a real action job — lets the
13342
+ // UI render the job's dispatch/progress inline. NULL for pure conversation.
13343
+ jobId: uuid("job_id").references(() => agentJobs.id, { onDelete: "set null" }),
13344
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow()
13345
+ },
13346
+ (table) => [
13347
+ index("idx_chat_messages_conversation").on(table.conversationId, table.createdAt),
13348
+ check("chat_messages_role_check", sql`${table.role} IN ('user','assistant')`)
13349
+ ]
13350
+ );
13351
+ }
13352
+ });
13353
+
13288
13354
  // ../../packages/db/src/schema/index.ts
13289
13355
  var schema_exports = {};
13290
13356
  __export(schema_exports, {
@@ -13326,8 +13392,10 @@ __export(schema_exports, {
13326
13392
  agents: () => agents,
13327
13393
  approvalRequests: () => approvalRequests,
13328
13394
  approvalRules: () => approvalRules,
13395
+ chatMessages: () => chatMessages,
13329
13396
  configuratorSessions: () => configuratorSessions,
13330
13397
  connectors: () => connectors,
13398
+ conversations: () => conversations,
13331
13399
  credentials: () => credentials,
13332
13400
  entities: () => entities,
13333
13401
  entityLlmKeys: () => entityLlmKeys,
@@ -13368,6 +13436,7 @@ var init_schema2 = __esm({
13368
13436
  init_auth();
13369
13437
  init_agent_connector_assignments();
13370
13438
  init_agent_workspaces();
13439
+ init_chat_messages();
13371
13440
  }
13372
13441
  });
13373
13442
 
@@ -13428,7 +13497,9 @@ var init_credentials2 = __esm({
13428
13497
  var init_agents2 = __esm({
13429
13498
  "../../packages/db/src/repos/agents.ts"() {
13430
13499
  "use strict";
13500
+ init_src2();
13431
13501
  init_agents();
13502
+ init_entities();
13432
13503
  }
13433
13504
  });
13434
13505
 
@@ -0,0 +1,10 @@
1
+ -- 0023_agent_schedules_notify_on_success.sql
2
+ -- Per-schedule success confirmation (2026-05-31):
3
+ -- ADD COLUMN agent_schedules.notify_on_success (boolean, not null, default false)
4
+ --
5
+ -- Opt-in flag. When true, the cron tick sets the fired job's chat_id so the
6
+ -- runner forces the agent to deliver a success confirmation before completing.
7
+ -- Idempotent (IF NOT EXISTS guard).
8
+
9
+ ALTER TABLE agent_schedules
10
+ ADD COLUMN IF NOT EXISTS notify_on_success boolean NOT NULL DEFAULT false;
@@ -0,0 +1,11 @@
1
+ -- 0024_agent_jobs_dashboard_channel.sql
2
+ -- V4 — in-app ROOT chat (2026-05-31):
3
+ -- Allow 'dashboard' as an agent_jobs.channel value so the dashboard chat with
4
+ -- the ROOT agent reuses the same job lifecycle + thread continuity as Telegram.
5
+ -- Rebuild the CHECK constraint to include 'dashboard'. Idempotent.
6
+
7
+ ALTER TABLE agent_jobs DROP CONSTRAINT IF EXISTS agent_jobs_channel_check;
8
+
9
+ ALTER TABLE agent_jobs
10
+ ADD CONSTRAINT agent_jobs_channel_check
11
+ CHECK (channel IN ('telegram','api','whatsapp','internal','cron','task-board','slack','discord','dashboard'));
@@ -0,0 +1,9 @@
1
+ -- 0025_agent_jobs_conversational.sql
2
+ -- V4 — in-app ROOT chat, "jobless" conversation model (2026-05-31):
3
+ -- A chat turn that only used conversational tools (text + memory + delivery)
4
+ -- is conversation, not work — it belongs in /chat, never in /jobs. The runner
5
+ -- flags it at completion; the dashboard filters Runs/stats on this column.
6
+ -- Default false → all existing + non-chat jobs remain visible as Runs.
7
+
8
+ ALTER TABLE agent_jobs
9
+ ADD COLUMN IF NOT EXISTS conversational boolean NOT NULL DEFAULT false;
@@ -0,0 +1,19 @@
1
+ -- 0026_chat_messages.sql
2
+ -- V4 — conversation-first in-app chat (2026-05-31):
3
+ -- A conversation is NOT a job. Pure chat turns (text + memory) are stored here
4
+ -- and never create an agent_jobs row. Only an ACTION turn escalates to a job,
5
+ -- whose id is linked via job_id so the UI shows progress inline.
6
+
7
+ CREATE TABLE IF NOT EXISTS chat_messages (
8
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
9
+ entity_id uuid REFERENCES entities(id) ON DELETE CASCADE,
10
+ agent_id uuid NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
11
+ thread_id text NOT NULL DEFAULT 'main',
12
+ role text NOT NULL CHECK (role IN ('user','assistant')),
13
+ content text NOT NULL,
14
+ job_id uuid REFERENCES agent_jobs(id) ON DELETE SET NULL,
15
+ created_at timestamptz DEFAULT now()
16
+ );
17
+
18
+ CREATE INDEX IF NOT EXISTS idx_chat_messages_thread
19
+ ON chat_messages (entity_id, agent_id, thread_id, created_at);
@@ -0,0 +1,6 @@
1
+ -- 0027_drop_agent_jobs_conversational.sql
2
+ -- Revert the short-lived "conversational" flag (migration 0025). The in-app chat
3
+ -- is now conversation-first: pure chat lives in chat_messages and never creates
4
+ -- an agent_jobs row at all, so flagging/hiding jobs is no longer needed.
5
+
6
+ ALTER TABLE agent_jobs DROP COLUMN IF EXISTS conversational;
@@ -0,0 +1,27 @@
1
+ -- 0028_conversations.sql
2
+ -- V4 chat — multi-conversation backbone (2026-06-01):
3
+ -- Group chat_messages under named `conversations` (the sidebar entries), so
4
+ -- the chat gets multiple threads, "+ New", recency sort, and a clean history
5
+ -- model. Replaces the single hardcoded thread_id on chat_messages.
6
+
7
+ CREATE TABLE IF NOT EXISTS conversations (
8
+ id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
9
+ entity_id uuid REFERENCES entities(id) ON DELETE CASCADE,
10
+ agent_id uuid NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
11
+ title text NOT NULL DEFAULT '',
12
+ created_at timestamptz DEFAULT now(),
13
+ updated_at timestamptz DEFAULT now()
14
+ );
15
+
16
+ CREATE INDEX IF NOT EXISTS idx_conversations_entity_agent
17
+ ON conversations (entity_id, agent_id, updated_at);
18
+
19
+ ALTER TABLE chat_messages
20
+ ADD COLUMN IF NOT EXISTS conversation_id uuid REFERENCES conversations(id) ON DELETE CASCADE;
21
+
22
+ -- thread_id is superseded by conversation_id. Existing dev rows (if any) had
23
+ -- thread_id='main' and get a NULL conversation_id (orphaned, not shown).
24
+ ALTER TABLE chat_messages DROP COLUMN IF EXISTS thread_id;
25
+
26
+ CREATE INDEX IF NOT EXISTS idx_chat_messages_conversation
27
+ ON chat_messages (conversation_id, created_at);
@@ -0,0 +1,33 @@
1
+ -- 0029_backfill_root_agent.sql
2
+ -- Brique F — "ROOT = origin orchestrator" (2026-06-01).
3
+ --
4
+ -- Designate a ROOT for any entity that has at least one orchestrator but no
5
+ -- root_agent_id yet: the earliest-created orchestrator wins. Additive only —
6
+ -- entities that already have a ROOT (and its configured grants) are left
7
+ -- untouched, so a manually-set ROOT and its powers are preserved.
8
+ --
9
+ -- Going forward, createAgentRepo auto-designates the first orchestrator of an
10
+ -- entity as ROOT and forces subsequent ones under it. Grants start all-off
11
+ -- (opt-in powers in Settings → ROOT agent); writing them explicitly matters
12
+ -- because a null root_grants parses to all-on (un-gated meta-tools).
13
+ --
14
+ -- Idempotent: the `root_agent_id IS NULL` guard makes re-runs a no-op.
15
+
16
+ UPDATE entities e
17
+ SET
18
+ root_agent_id = sub.first_orch,
19
+ root_grants = '{"createAgent":false,"createSkill":false,"updateSkill":false,"assignSkill":false,"createMcp":false,"autonomy":"propose_confirm"}'::jsonb,
20
+ updated_at = now()
21
+ FROM (
22
+ SELECT a.entity_id, a.id AS first_orch
23
+ FROM agents a
24
+ WHERE a.role = 'orchestrator'
25
+ AND NOT EXISTS (
26
+ SELECT 1 FROM agents a2
27
+ WHERE a2.entity_id = a.entity_id
28
+ AND a2.role = 'orchestrator'
29
+ AND (a2.created_at < a.created_at OR (a2.created_at = a.created_at AND a2.id < a.id))
30
+ )
31
+ ) AS sub
32
+ WHERE e.id = sub.entity_id
33
+ AND e.root_agent_id IS NULL;