@agent-native/core 0.145.7 → 0.146.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 (186) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +5 -1
  3. package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +37 -11
  4. package/corpus/templates/analytics/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  5. package/corpus/templates/analytics/actions/get-sql-dashboard.ts +20 -4
  6. package/corpus/templates/analytics/actions/migrate-first-party-analytics-to-bigquery.ts +59 -24
  7. package/corpus/templates/analytics/app/pages/settings/AlertRulesSettingsCard.tsx +3 -2
  8. package/corpus/templates/analytics/changelog/2026-08-07-analytics-migrations-now-use-bounded-pressure-aware-backgrou.md +6 -0
  9. package/corpus/templates/analytics/changelog/2026-08-07-settings-skeleton-placeholders.md +6 -0
  10. package/corpus/templates/analytics/changelog/2026-08-07-template-activity-charts-now-show-only-core-agent-native-app.md +6 -0
  11. package/corpus/templates/analytics/netlify.toml +1 -1
  12. package/corpus/templates/analytics/package.json +1 -0
  13. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +110 -0
  14. package/corpus/templates/analytics/scripts/migrate-production.ts +24 -0
  15. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +13 -13
  16. package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +448 -0
  17. package/corpus/templates/analytics/server/jobs/analytics-rollup-backfill.ts +11 -2
  18. package/corpus/templates/analytics/server/lib/analytics-rollup-lock.ts +4 -5
  19. package/corpus/templates/analytics/server/lib/canonical-first-party-dashboard-repair.ts +35 -0
  20. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +3 -5
  21. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +10 -4
  22. package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +4 -11
  23. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +74 -28
  24. package/corpus/templates/analytics/server/plugins/analytics-rollup-backfill-jobs.ts +2 -5
  25. package/corpus/templates/analytics/server/plugins/db.ts +56 -3
  26. package/corpus/templates/analytics/server/routes/api/analytics-bigquery/backfill.post.ts +55 -0
  27. package/corpus/templates/analytics/server/routes/api/dashboard-agent-context.json.get.ts +22 -4
  28. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +5 -1
  29. package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +37 -11
  30. package/corpus/templates/assets/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  31. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +5 -1
  32. package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +37 -11
  33. package/corpus/templates/brain/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  34. package/corpus/templates/brain/server/lib/connectors.ts +38 -14
  35. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +5 -1
  36. package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +37 -11
  37. package/corpus/templates/calendar/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  38. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -1
  39. package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +37 -11
  40. package/corpus/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  41. package/corpus/templates/chat/AGENTS.md +3 -0
  42. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +5 -1
  43. package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +37 -11
  44. package/corpus/templates/clips/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  45. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +5 -1
  46. package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +37 -11
  47. package/corpus/templates/content/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  48. package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +37 -11
  49. package/corpus/templates/crm/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  50. package/corpus/templates/crm/app/components/crm/IntelligenceSettings.tsx +21 -3
  51. package/corpus/templates/crm/app/components/crm/settings/ConnectionSettings.tsx +23 -5
  52. package/corpus/templates/crm/app/components/crm/settings/FieldsSettings.tsx +24 -5
  53. package/corpus/templates/crm/app/components/crm/settings/ListsSettings.tsx +23 -3
  54. package/corpus/templates/crm/changelog/2026-08-07-settings-loading-skeletons.md +6 -0
  55. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +5 -1
  56. package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +37 -11
  57. package/corpus/templates/design/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  58. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +5 -1
  59. package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +37 -11
  60. package/corpus/templates/dispatch/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  61. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +5 -1
  62. package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +37 -11
  63. package/corpus/templates/factory/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  64. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +5 -1
  65. package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +37 -11
  66. package/corpus/templates/forms/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  67. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +5 -1
  68. package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +37 -11
  69. package/corpus/templates/macros/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  70. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +5 -1
  71. package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +37 -11
  72. package/corpus/templates/mail/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  73. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +5 -1
  74. package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +37 -11
  75. package/corpus/templates/plan/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  76. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +5 -1
  77. package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +37 -11
  78. package/corpus/templates/slides/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  79. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +13 -0
  80. package/corpus/templates/slides/app/components/editor/GeneratingSlidePreview.tsx +5 -0
  81. package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +5 -0
  82. package/corpus/templates/slides/app/components/presentation/PresenterView.tsx +5 -0
  83. package/corpus/templates/slides/app/pages/DeckEditor.tsx +3 -0
  84. package/corpus/templates/slides/app/pages/Presentation.tsx +3 -0
  85. package/corpus/templates/slides/app/pages/SharedPresentation.tsx +5 -0
  86. package/corpus/templates/slides/app/routes/slide.tsx +10 -5
  87. package/corpus/templates/slides/changelog/2026-08-07-slide-previews-and-present-now-keep-deck-colors-consistent.md +6 -0
  88. package/corpus/templates/slides/server/db/schema.ts +1 -0
  89. package/corpus/templates/slides/server/handlers/share.ts +51 -3
  90. package/corpus/templates/slides/server/plugins/db.ts +5 -0
  91. package/corpus/templates/slides/shared/api.ts +2 -0
  92. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +5 -1
  93. package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +37 -11
  94. package/corpus/templates/tasks/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  95. package/dist/cli/code-agent-executor.js +8 -3
  96. package/dist/client/ConnectBuilderCard.d.ts +7 -7
  97. package/dist/client/ConnectBuilderCard.js +45 -20
  98. package/dist/client/components/ApiKeySettings.js +2 -5
  99. package/dist/client/org/TeamPage.js +4 -2
  100. package/dist/client/settings/AccountSettingsCard.js +2 -1
  101. package/dist/client/settings/AgentsSection.js +2 -1
  102. package/dist/client/settings/SecretsSection.js +3 -2
  103. package/dist/client/settings/SettingsPanel.js +6 -12
  104. package/dist/client/settings/SettingsSkeleton.d.ts +12 -0
  105. package/dist/client/settings/SettingsSkeleton.js +12 -0
  106. package/dist/client/settings/VoiceTranscriptionSection.js +5 -4
  107. package/dist/client/settings/index.d.ts +1 -0
  108. package/dist/client/settings/index.js +1 -0
  109. package/dist/config.d.ts +9 -2
  110. package/dist/config.js +38 -2
  111. package/dist/db/client.d.ts +26 -8
  112. package/dist/db/client.js +200 -9
  113. package/dist/db/create-get-db.js +2 -2
  114. package/dist/db/ddl-guard.js +3 -1
  115. package/dist/db/ensure-additive-columns.d.ts +2 -0
  116. package/dist/db/ensure-additive-columns.js +5 -2
  117. package/dist/db/index.d.ts +2 -2
  118. package/dist/db/index.js +2 -2
  119. package/dist/db/migrations.d.ts +11 -54
  120. package/dist/db/migrations.js +70 -0
  121. package/dist/deploy/build.js +5 -1
  122. package/dist/jobs/index.d.ts +1 -0
  123. package/dist/jobs/index.js +1 -0
  124. package/dist/jobs/run-history.d.ts +4 -0
  125. package/dist/jobs/run-history.js +44 -0
  126. package/dist/provider-api/actions/provider-api.d.ts +4 -4
  127. package/dist/scripts/docs/search.js +3 -2
  128. package/dist/secrets/routes.d.ts +6 -6
  129. package/dist/server/agent-chat/prompt-resources.js +4 -3
  130. package/dist/server/agent-chat-plugin.js +6 -4
  131. package/dist/server/agents-bundle.d.ts +20 -3
  132. package/dist/server/agents-bundle.js +57 -30
  133. package/dist/server/auth-plugin.js +5 -0
  134. package/dist/server/better-auth-instance.js +2 -63
  135. package/dist/server/better-auth-migrations.d.ts +8 -0
  136. package/dist/server/better-auth-migrations.js +179 -0
  137. package/dist/server/edge.d.ts +2 -0
  138. package/dist/server/edge.js +2 -0
  139. package/dist/server/index.d.ts +2 -0
  140. package/dist/server/index.js +2 -0
  141. package/dist/server/release-migrations.d.ts +8 -0
  142. package/dist/server/release-migrations.js +24 -0
  143. package/dist/server/sweep-runtime.d.ts +1 -1
  144. package/dist/server/sweep-runtime.js +15 -0
  145. package/dist/shared/runtime-config.js +1 -1
  146. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -1
  147. package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +37 -11
  148. package/dist/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  149. package/dist/templates/chat/AGENTS.md +3 -0
  150. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +5 -1
  151. package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +37 -11
  152. package/dist/templates/default/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  153. package/dist/templates/default/AGENTS.md +3 -0
  154. package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +37 -11
  155. package/dist/templates/headless/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  156. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +5 -1
  157. package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +37 -11
  158. package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  159. package/dist/templates/workspace-core/AGENTS.md +3 -0
  160. package/dist/templates/workspace-root/AGENTS.md +3 -0
  161. package/dist/vite/agent-native-config-loader.d.ts +10 -0
  162. package/dist/vite/agent-native-config-loader.js +56 -0
  163. package/dist/vite/agents-bundle-plugin.d.ts +5 -1
  164. package/dist/vite/agents-bundle-plugin.js +29 -6
  165. package/dist/vite/client.d.ts +4 -2
  166. package/dist/vite/client.js +4 -49
  167. package/dist/vite/index.d.ts +2 -2
  168. package/dist/vite/index.js +1 -1
  169. package/docs/content/agent-native-config.mdx +43 -17
  170. package/docs/content/environment-variables.mdx +1 -1
  171. package/package.json +3 -3
  172. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +5 -1
  173. package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +37 -11
  174. package/src/templates/chat/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  175. package/src/templates/chat/AGENTS.md +3 -0
  176. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +5 -1
  177. package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +37 -11
  178. package/src/templates/default/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  179. package/src/templates/default/AGENTS.md +3 -0
  180. package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +37 -11
  181. package/src/templates/headless/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  182. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +5 -1
  183. package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +37 -11
  184. package/src/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +13 -2
  185. package/src/templates/workspace-core/AGENTS.md +3 -0
  186. package/src/templates/workspace-root/AGENTS.md +3 -0
@@ -226,6 +226,56 @@ function resolveMigrationSql(sql, pg) {
226
226
  * extend the same list concurrently), giving new entries a name is what makes
227
227
  * them immune to the collision class described above.
228
228
  */
229
+ /**
230
+ * True in a production serverless runtime that serves user REQUESTS.
231
+ *
232
+ * Deliberately mirrors the analytics template's own predicate rather than
233
+ * importing it: `packages/core/src/db` must not depend on a template, and the
234
+ * agent/background modules that carry the sibling predicates would introduce a
235
+ * cycle here.
236
+ */
237
+ function isServerlessRequestRuntime() {
238
+ if (process.env.NODE_ENV !== "production")
239
+ return false;
240
+ return (process.env.NETLIFY === "true" ||
241
+ Boolean(process.env.NETLIFY_FUNCTION_NAME) ||
242
+ Boolean(process.env.AWS_LAMBDA_FUNCTION_NAME) ||
243
+ Boolean(process.env.LAMBDA_TASK_ROOT) ||
244
+ process.env.AWS_EXECUTION_ENV?.startsWith("AWS_Lambda") === true ||
245
+ process.env.VERCEL === "1");
246
+ }
247
+ /**
248
+ * A runtime that is ALLOWED to migrate: scheduled jobs and durable background
249
+ * workers, which are off the request path and may take as long as they need.
250
+ *
251
+ * Set by whichever runtime claims migration duty. Analytics sets its own
252
+ * equivalent flag before running the scheduled rollup.
253
+ */
254
+ function isMigrationAuthorizedRuntime() {
255
+ return (globalThis.__AGENT_NATIVE_MIGRATION_RUNTIME__ === true);
256
+ }
257
+ /**
258
+ * Run an explicit release-time migration job with migration duty enabled.
259
+ *
260
+ * The flag is process-local and restored even when the job fails, so a build
261
+ * step can opt in without creating a permanent escape hatch for request code.
262
+ */
263
+ export async function withMigrationRuntime(run) {
264
+ const runtime = globalThis;
265
+ const previous = runtime.__AGENT_NATIVE_MIGRATION_RUNTIME__;
266
+ runtime.__AGENT_NATIVE_MIGRATION_RUNTIME__ = true;
267
+ try {
268
+ return await run();
269
+ }
270
+ finally {
271
+ if (previous === undefined) {
272
+ delete runtime.__AGENT_NATIVE_MIGRATION_RUNTIME__;
273
+ }
274
+ else {
275
+ runtime.__AGENT_NATIVE_MIGRATION_RUNTIME__ = previous;
276
+ }
277
+ }
278
+ }
229
279
  export function runMigrations(migrations, options) {
230
280
  const table = options?.table;
231
281
  if (!table ||
@@ -256,6 +306,26 @@ export function runMigrations(migrations, options) {
256
306
  return async () => { };
257
307
  const namedTable = `${table}_named`;
258
308
  return async () => {
309
+ // Migrations are schema DDL plus an introspection pass. On serverless
310
+ // "first touch" is EVERY cold start, so this lands on the critical path of
311
+ // a user request — measured at ~5.5-8.6s for the version check alone on a
312
+ // 180-table database, with 4-6 copies running concurrently under load.
313
+ //
314
+ // Guarded HERE rather than at each call site on purpose. The analytics
315
+ // template guarded its own runner in #2708; three core plugins
316
+ // (org, context-xray, observational-memory) kept calling this unguarded,
317
+ // so the probe storm survived the fix that was supposed to end it. A
318
+ // fourth special case would have shipped the same bug a fourth time.
319
+ //
320
+ // Schema still has to exist: a scheduled/background runtime sets
321
+ // `__AGENT_NATIVE_MIGRATION_RUNTIME__`, and `runInServerlessRequest` is
322
+ // the explicit opt-in for a caller that genuinely cannot defer.
323
+ if (options?.runInServerlessRequest !== true &&
324
+ isServerlessRequestRuntime() &&
325
+ !isMigrationAuthorizedRuntime()) {
326
+ console.info(`[migrations] Skipping "${table}" migrations in a serverless request runtime`);
327
+ return;
328
+ }
259
329
  try {
260
330
  // Check for Cloudflare D1 binding (only if DATABASE_URL not set)
261
331
  const d1 = getDialect() === "d1"
@@ -27,6 +27,7 @@ import { DEFAULT_SPECULATION_RULES_PATH, resolveSsrCacheHeaders, } from "../shar
27
27
  import { mcpEmbedStaticAssetRouteRules } from "../shared/mcp-embed-headers.js";
28
28
  import { AGENT_NATIVE_SOCIAL_IMAGE_ALT, AGENT_NATIVE_SOCIAL_IMAGE_CACHE_BUSTER, AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT, AGENT_NATIVE_SOCIAL_IMAGE_PATH, AGENT_NATIVE_SOCIAL_IMAGE_TYPE, AGENT_NATIVE_SOCIAL_IMAGE_WIDTH, } from "../shared/social-meta.js";
29
29
  import { generateActionRegistryForProject } from "../vite/action-types-plugin.js";
30
+ import { createAgentNativeConfigContext, loadResolvedAgentNativeConfig, } from "../vite/agent-native-config-loader.js";
30
31
  import { cloneServerBundleForFunction, copyDir } from "./function-bundle.js";
31
32
  import { collectImmutableAssetPaths, IMMUTABLE_ASSET_CACHE_CONTROL, IMMUTABLE_ASSET_CACHE_HEADERS, prefixAssetPath, } from "./immutable-assets.js";
32
33
  import { discoverApiRoutes, discoverPlugins, discoverActionFiles, getMissingDefaultPlugins, DEFAULT_PLUGIN_REGISTRY, } from "./route-discovery.js";
@@ -3493,6 +3494,7 @@ async function buildWithNitro() {
3493
3494
  // own virtual module registration. Both paths reuse `readAgentsBundleFromFs`
3494
3495
  // from `server/agents-bundle.ts` to guarantee identical content.
3495
3496
  const { readAgentsBundleFromFs } = await import("../server/agents-bundle.js");
3497
+ const nitroAgentConfig = await loadResolvedAgentNativeConfig(cwd, createAgentNativeConfigContext("build", process.env.NODE_ENV === "development" ? "development" : "production"));
3496
3498
  // Resolve the workspace core (if present) up front so the bundle embeds
3497
3499
  // enterprise-wide AGENTS.md + skills alongside the template's.
3498
3500
  const nitroWorkspaceCore = await getWorkspaceCoreExports(cwd);
@@ -3504,7 +3506,9 @@ async function buildWithNitro() {
3504
3506
  }
3505
3507
  : null;
3506
3508
  const agentsBundleModuleSource = () => {
3507
- const bundle = readAgentsBundleFromFs(cwd, nitroWorkspaceSource);
3509
+ const bundle = readAgentsBundleFromFs(cwd, nitroWorkspaceSource, {
3510
+ instructions: nitroAgentConfig.instructions,
3511
+ });
3508
3512
  return `// AUTO-GENERATED by @agent-native/core deploy build (Nitro virtual)
3509
3513
  // Contains the inlined AGENTS.md + .agents/skills/ content from the template,
3510
3514
  // merged with the workspace core's AGENTS.md + skills/ when present.
@@ -3,3 +3,4 @@ export { processRecurringJobs, parseJobFrontmatter, buildJobContent, type JobFro
3
3
  export { getAutomationSchedulerHealth, recordAutomationSchedulerHealth, type AutomationSchedulerHealth, } from "./scheduler-health.js";
4
4
  export { RECURRING_JOBS_SWEEP_PATH, RECURRING_JOBS_SWEEP_TOKEN_SUBJECT, } from "./scheduler-dispatch.js";
5
5
  export { createJobTools } from "./tools.js";
6
+ export { AUTOMATION_RUN_MIGRATIONS, runAutomationRunMigrations, } from "./run-history.js";
@@ -3,3 +3,4 @@ export { processRecurringJobs, parseJobFrontmatter, buildJobContent, } from "./s
3
3
  export { getAutomationSchedulerHealth, recordAutomationSchedulerHealth, } from "./scheduler-health.js";
4
4
  export { RECURRING_JOBS_SWEEP_PATH, RECURRING_JOBS_SWEEP_TOKEN_SUBJECT, } from "./scheduler-dispatch.js";
5
5
  export { createJobTools } from "./tools.js";
6
+ export { AUTOMATION_RUN_MIGRATIONS, runAutomationRunMigrations, } from "./run-history.js";
@@ -1,3 +1,4 @@
1
+ import { type MigrationEntry } from "../db/migrations.js";
1
2
  /**
2
3
  * "interrupted" is derived at read time, never stored: a process killed
3
4
  * mid-run cannot write its own outcome, so a row left running long past the
@@ -30,6 +31,9 @@ export interface StartAutomationRunInput {
30
31
  /** A pre-created row still waiting for its background worker handoff. */
31
32
  dispatchPending?: boolean;
32
33
  }
34
+ /** Authoritative release-time schema for durable automation history. */
35
+ export declare const AUTOMATION_RUN_MIGRATIONS: MigrationEntry[];
36
+ export declare function runAutomationRunMigrations(nitroApp: unknown): Promise<void>;
33
37
  /**
34
38
  * Record an automation execution. Manual runs create the row before dispatch,
35
39
  * so `dispatchPending` distinguishes that durable handoff from a run that has
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
2
2
  import { z } from "zod";
3
3
  import { getDbExec, intType, isPostgres } from "../db/client.js";
4
4
  import { ensureColumnExists, ensureIndexExists, ensureTableExists, } from "../db/ddl-guard.js";
5
+ import { runMigrations } from "../db/migrations.js";
5
6
  import { emit as emitBusEvent, registerEvent } from "../event-bus/index.js";
6
7
  registerEvent({
7
8
  name: "automation.run.finished",
@@ -32,6 +33,49 @@ const INTERRUPTED_RUN_MESSAGE = "Worker stopped before a terminal result was rec
32
33
  const CLAIM_LEASE_MS = RUN_LIVENESS_CEILING_MS;
33
34
  /** Rows kept per automation, so a per-minute schedule cannot grow forever. */
34
35
  const RUNS_RETAINED_PER_AUTOMATION = 50;
36
+ /** Authoritative release-time schema for durable automation history. */
37
+ export const AUTOMATION_RUN_MIGRATIONS = [
38
+ {
39
+ version: 1,
40
+ name: "automation-runs-table",
41
+ sql: `
42
+ CREATE TABLE IF NOT EXISTS ${TABLE} (
43
+ id TEXT PRIMARY KEY,
44
+ owner TEXT NOT NULL,
45
+ automation TEXT NOT NULL,
46
+ path TEXT NOT NULL,
47
+ scope TEXT,
48
+ org_id TEXT,
49
+ run_id TEXT,
50
+ thread_id TEXT,
51
+ status TEXT NOT NULL DEFAULT 'running',
52
+ started_at INTEGER NOT NULL,
53
+ finished_at INTEGER,
54
+ error TEXT,
55
+ claimed_at INTEGER,
56
+ dispatch_pending INTEGER NOT NULL DEFAULT 0
57
+ );
58
+ CREATE INDEX IF NOT EXISTS idx_${TABLE}_owner_automation
59
+ ON ${TABLE} (owner, automation, started_at)
60
+ `,
61
+ },
62
+ {
63
+ version: 2,
64
+ name: "automation-runs-claimed-at",
65
+ sql: `ALTER TABLE ${TABLE} ADD COLUMN IF NOT EXISTS claimed_at INTEGER`,
66
+ },
67
+ {
68
+ version: 3,
69
+ name: "automation-runs-dispatch-pending",
70
+ sql: `ALTER TABLE ${TABLE}
71
+ ADD COLUMN IF NOT EXISTS dispatch_pending INTEGER NOT NULL DEFAULT 0`,
72
+ },
73
+ ];
74
+ export async function runAutomationRunMigrations(nitroApp) {
75
+ await runMigrations(AUTOMATION_RUN_MIGRATIONS, {
76
+ table: "_automation_run_migrations",
77
+ })(nitroApp);
78
+ }
35
79
  let _initPromise;
36
80
  async function ensureTable() {
37
81
  if (!_initPromise) {
@@ -314,6 +314,7 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
314
314
  id?: undefined;
315
315
  provider?: undefined;
316
316
  deleted?: undefined;
317
+ message?: undefined;
317
318
  providers: {
318
319
  id: string;
319
320
  label: string;
@@ -327,37 +328,36 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
327
328
  found?: undefined;
328
329
  registered?: undefined;
329
330
  label?: undefined;
330
- message?: undefined;
331
331
  } | {
332
332
  id?: undefined;
333
333
  count?: undefined;
334
334
  deleted?: undefined;
335
+ message?: undefined;
335
336
  providers?: undefined;
336
337
  found: boolean;
337
338
  provider: import("../custom-registry.js").CustomProviderConfig;
338
339
  registered?: undefined;
339
340
  label?: undefined;
340
- message?: undefined;
341
341
  } | {
342
342
  count?: undefined;
343
343
  provider?: undefined;
344
344
  deleted?: undefined;
345
+ message?: undefined;
345
346
  providers?: undefined;
346
347
  found: boolean;
347
348
  id: string;
348
349
  registered?: undefined;
349
350
  label?: undefined;
350
- message?: undefined;
351
351
  } | {
352
352
  count?: undefined;
353
353
  provider?: undefined;
354
+ message?: undefined;
354
355
  providers?: undefined;
355
356
  found?: undefined;
356
357
  deleted: boolean;
357
358
  id: string;
358
359
  registered?: undefined;
359
360
  label?: undefined;
360
- message?: undefined;
361
361
  } | {
362
362
  count?: undefined;
363
363
  provider?: undefined;
@@ -127,12 +127,13 @@ async function loadAgentBundleDocs() {
127
127
  body: bundle.workspaceAgentsMd,
128
128
  });
129
129
  }
130
- if (bundle.agentsMd?.trim()) {
130
+ const runtimeAgentsMd = bundle.runtimeAgentsMd ?? bundle.agentsMd;
131
+ if (runtimeAgentsMd?.trim()) {
131
132
  docs.push({
132
133
  slug: "agents-template",
133
134
  title: "Template AGENTS.md",
134
135
  description: "Full bundled template/app agent instructions.",
135
- body: bundle.agentsMd,
136
+ body: runtimeAgentsMd,
136
137
  });
137
138
  }
138
139
  // Only runtime-visible skills are searchable/readable here — `scope: dev`
@@ -37,17 +37,17 @@ export declare function createWriteSecretHandler(): import("h3").EventHandlerWit
37
37
  ok?: undefined;
38
38
  status?: undefined;
39
39
  } | {
40
+ error?: undefined;
40
41
  ok: boolean;
41
42
  status: string;
42
- error?: undefined;
43
43
  } | {
44
44
  ok?: undefined;
45
45
  error: string;
46
46
  removed?: undefined;
47
47
  } | {
48
+ error?: undefined;
48
49
  ok: boolean;
49
50
  removed: boolean;
50
- error?: undefined;
51
51
  }>>;
52
52
  /**
53
53
  * POST /_agent-native/secrets/:key/test — validate an optional candidate value
@@ -58,13 +58,13 @@ export declare function createTestSecretHandler(): import("h3").EventHandlerWith
58
58
  error: string;
59
59
  note?: undefined;
60
60
  } | {
61
+ error?: undefined;
61
62
  ok: boolean;
62
63
  note?: undefined;
63
- error?: undefined;
64
64
  } | {
65
+ error?: undefined;
65
66
  ok: boolean;
66
67
  note: string;
67
- error?: undefined;
68
68
  } | {
69
69
  note?: undefined;
70
70
  ok: boolean;
@@ -95,11 +95,11 @@ export interface AdHocSecretPayload {
95
95
  export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
96
96
  error: string;
97
97
  } | {
98
+ error?: undefined;
98
99
  ok: boolean;
99
100
  key: string;
100
- error?: undefined;
101
101
  } | {
102
+ error?: undefined;
102
103
  ok: boolean;
103
104
  removed: boolean;
104
- error?: undefined;
105
105
  }>>;
@@ -631,13 +631,14 @@ export async function loadResourcesForPrompt(owner, compact = false, selfAppId,
631
631
  });
632
632
  addSection(block, "required");
633
633
  }
634
- // 2. Template AGENTS.md — always included (critical template instructions).
635
- if (bundle.agentsMd.trim()) {
634
+ // 2. Runtime instruction file — always included when configured.
635
+ const runtimeAgentsMd = bundle.runtimeAgentsMd ?? bundle.agentsMd;
636
+ if (runtimeAgentsMd.trim()) {
636
637
  const block = promptResourceBlock({
637
638
  name: "AGENTS.md",
638
639
  scope: "template",
639
640
  path: "AGENTS.md",
640
- content: bundle.agentsMd,
641
+ content: runtimeAgentsMd,
641
642
  maxChars: promptResourceMaxChars,
642
643
  readHint: 'Use docs-search --slug "agents-template" to read the full template AGENTS.md.',
643
644
  });
@@ -4885,10 +4885,12 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
4885
4885
  catch (error) {
4886
4886
  console.warn("[recurring-jobs] Scheduler module unavailable:", error instanceof Error ? error.message : error);
4887
4887
  }
4888
- // A non-Netlify self-dispatch only waits for the request to leave the
4889
- // current invocation. Keep the durable history row as a retryable queue
4890
- // so a frozen serverless handoff is recovered on the next sweep.
4891
- if (!isBackgroundRuntime && !sweepsDisabled) {
4888
+ // A synchronous self-dispatch only waits for the request to leave the
4889
+ // current invocation. Long-lived runtimes keep this retryable-queue
4890
+ // backstop; serverless runtimes use their durable scheduler instead.
4891
+ if (!isBackgroundRuntime &&
4892
+ !disableRecurringJobsRuntime &&
4893
+ !sweepsDisabled) {
4892
4894
  (() => {
4893
4895
  let inFlight = false;
4894
4896
  const sweep = async () => {
@@ -15,7 +15,8 @@
15
15
  * 2. Filesystem fallback — `process.cwd()/AGENTS.md` +
16
16
  * `process.cwd()/.agents/skills/` (or legacy `.agent/skills/`). Only reliable in local dev and Node
17
17
  * production (`agent-native start`); not on Netlify/Vercel/CF at runtime.
18
- * 3. Empty bundle — everything silently returns empty strings.
18
+ * 3. Configuration and filesystem failures propagate so a broken bundle is
19
+ * visible instead of being mistaken for an app with no instructions.
19
20
  *
20
21
  * Result is cached in module scope so it's only computed once per cold start.
21
22
  */
@@ -68,8 +69,15 @@ export interface Skill {
68
69
  files: Record<string, string>;
69
70
  }
70
71
  export interface AgentsBundle {
71
- /** Contents of the template's AGENTS.md (empty string if missing). */
72
+ /**
73
+ * Legacy alias for the runtime instruction file. Empty when an explicitly
74
+ * configured runtime file is missing.
75
+ */
72
76
  agentsMd: string;
77
+ /** Contents of the runtime agent's selected instruction file. */
78
+ runtimeAgentsMd: string;
79
+ /** Contents of the development agent's selected instruction file. */
80
+ developmentAgentsMd: string;
73
81
  /**
74
82
  * Contents of the workspace core's AGENTS.md, if the app is inside an
75
83
  * enterprise monorepo with a `workspaceCore` configured. Empty string
@@ -86,6 +94,14 @@ export interface AgentsBundle {
86
94
  */
87
95
  skills: Record<string, Skill>;
88
96
  }
97
+ export interface AgentsBundleReadOptions {
98
+ instructions?: AgentNativeInstructionsConfig;
99
+ }
100
+ export interface AgentInstructionPaths {
101
+ runtime: string;
102
+ development: string;
103
+ }
104
+ export declare function resolveAgentInstructionPaths(instructions?: AgentNativeInstructionsConfig): AgentInstructionPaths;
89
105
  export declare function normalizeSkillScope(raw: string | undefined): SkillScope;
90
106
  /**
91
107
  * Parse the YAML frontmatter at the top of a skill file.
@@ -97,6 +113,7 @@ export declare function normalizeSkillScope(raw: string | undefined): SkillScope
97
113
  * - Literal scalar: `description: |\n multi\n line` → "multi\nline"
98
114
  */
99
115
  export declare function parseSkillFrontmatter(content: string): Partial<SkillMeta>;
116
+ import type { AgentNativeInstructionsConfig } from "../config.js";
100
117
  /**
101
118
  * Paths to a workspace-core's agent resources, for merging into a template's
102
119
  * bundle. All fields optional — pass null for any missing piece.
@@ -117,7 +134,7 @@ export interface WorkspaceAgentsSource {
117
134
  *
118
135
  * Synchronous — the Vite plugin's load hook calls it inline during the build.
119
136
  */
120
- export declare function readAgentsBundleFromFs(cwd: string, workspaceSource?: WorkspaceAgentsSource | null): AgentsBundle;
137
+ export declare function readAgentsBundleFromFs(cwd: string, workspaceSource?: WorkspaceAgentsSource | null, options?: AgentsBundleReadOptions): AgentsBundle;
121
138
  /**
122
139
  * Load the agents bundle. Returns a cached result on subsequent calls.
123
140
  * Tries the virtual module first (works everywhere, including edge), then
@@ -15,12 +15,19 @@
15
15
  * 2. Filesystem fallback — `process.cwd()/AGENTS.md` +
16
16
  * `process.cwd()/.agents/skills/` (or legacy `.agent/skills/`). Only reliable in local dev and Node
17
17
  * production (`agent-native start`); not on Netlify/Vercel/CF at runtime.
18
- * 3. Empty bundle — everything silently returns empty strings.
18
+ * 3. Configuration and filesystem failures propagate so a broken bundle is
19
+ * visible instead of being mistaken for an app with no instructions.
19
20
  *
20
21
  * Result is cached in module scope so it's only computed once per cold start.
21
22
  */
22
23
  export const DEFAULT_SKILL_SCOPE = "both";
23
- const EMPTY = { agentsMd: "", workspaceAgentsMd: "", skills: {} };
24
+ const DEFAULT_AGENT_INSTRUCTIONS_PATH = "AGENTS.md";
25
+ export function resolveAgentInstructionPaths(instructions) {
26
+ return {
27
+ runtime: instructions?.runtime ?? DEFAULT_AGENT_INSTRUCTIONS_PATH,
28
+ development: instructions?.development ?? DEFAULT_AGENT_INSTRUCTIONS_PATH,
29
+ };
30
+ }
24
31
  let cached = null;
25
32
  /**
26
33
  * Coerce a raw frontmatter `scope` value into a known `SkillScope`. Unknown,
@@ -125,6 +132,23 @@ const READABLE_SUBFILE_EXTENSIONS = new Set([".md", ".txt", ".json"]);
125
132
  */
126
133
  const MAX_SUBFILE_BYTES = 64 * 1024;
127
134
  const MAX_SKILL_FILES_BYTES = 256 * 1024;
135
+ function readInstructionFile(cwd, relativePath) {
136
+ const normalizedPath = relativePath.replaceAll("\\", "/");
137
+ const root = fs.realpathSync(path.resolve(cwd));
138
+ const absolutePath = path.resolve(root, normalizedPath);
139
+ if (absolutePath !== root && !absolutePath.startsWith(`${root}${path.sep}`)) {
140
+ throw new Error(`Agent instruction path must stay inside the app root: ${relativePath}`);
141
+ }
142
+ if (!fs.existsSync(absolutePath))
143
+ return "";
144
+ const realPath = fs.realpathSync(absolutePath);
145
+ if (realPath !== root && !realPath.startsWith(`${root}${path.sep}`)) {
146
+ throw new Error(`Agent instruction path must stay inside the app root: ${relativePath}`);
147
+ }
148
+ if (!fs.statSync(realPath).isFile())
149
+ return "";
150
+ return fs.readFileSync(realPath, "utf-8");
151
+ }
128
152
  /**
129
153
  * Read one skills directory into a `Record<string, Skill>`. Extracted so
130
154
  * both the template and workspace-core paths can reuse it. `dirPrefix` is
@@ -214,15 +238,10 @@ function readSkillsDir(skillsDir, rootForRelative, out, skipExistingNames) {
214
238
  *
215
239
  * Synchronous — the Vite plugin's load hook calls it inline during the build.
216
240
  */
217
- export function readAgentsBundleFromFs(cwd, workspaceSource = null) {
218
- let agentsMd = "";
219
- try {
220
- const agentsMdPath = path.join(cwd, "AGENTS.md");
221
- if (fs.existsSync(agentsMdPath)) {
222
- agentsMd = fs.readFileSync(agentsMdPath, "utf-8");
223
- }
224
- }
225
- catch { }
241
+ export function readAgentsBundleFromFs(cwd, workspaceSource = null, options = {}) {
242
+ const instructionPaths = resolveAgentInstructionPaths(options.instructions);
243
+ const runtimeAgentsMd = readInstructionFile(cwd, instructionPaths.runtime);
244
+ const developmentAgentsMd = readInstructionFile(cwd, instructionPaths.development);
226
245
  let workspaceAgentsMd = "";
227
246
  if (workspaceSource?.agentsMdPath) {
228
247
  try {
@@ -249,7 +268,15 @@ export function readAgentsBundleFromFs(cwd, workspaceSource = null) {
249
268
  }
250
269
  catch { }
251
270
  }
252
- return { agentsMd, workspaceAgentsMd, skills };
271
+ return {
272
+ // Keep the old field useful for callers that only know about the runtime
273
+ // bundle. Audience-aware consumers should use the explicit fields.
274
+ agentsMd: runtimeAgentsMd,
275
+ runtimeAgentsMd,
276
+ developmentAgentsMd,
277
+ workspaceAgentsMd,
278
+ skills,
279
+ };
253
280
  }
254
281
  /**
255
282
  * Load the agents bundle. Returns a cached result on subsequent calls.
@@ -279,29 +306,29 @@ export async function loadAgentsBundle() {
279
306
  }
280
307
  // 2. Filesystem fallback — works in dev / Node prod. If a workspace core
281
308
  // is present in the ancestor chain, merge its skills + AGENTS.md in.
309
+ let workspaceSource = null;
282
310
  try {
283
- let workspaceSource = null;
284
- try {
285
- const { getWorkspaceCoreExports } = await import("../deploy/workspace-core.js");
286
- const ws = await getWorkspaceCoreExports(process.cwd());
287
- if (ws) {
288
- workspaceSource = {
289
- skillsDir: ws.skillsDir,
290
- agentsMdPath: ws.agentsMdPath,
291
- rootDir: ws.packageDir,
292
- };
293
- }
294
- }
295
- catch {
296
- // workspace-core discovery isn't available (e.g. edge runtime).
311
+ const { getWorkspaceCoreExports } = await import("../deploy/workspace-core.js");
312
+ const ws = await getWorkspaceCoreExports(process.cwd());
313
+ if (ws) {
314
+ workspaceSource = {
315
+ skillsDir: ws.skillsDir,
316
+ agentsMdPath: ws.agentsMdPath,
317
+ rootDir: ws.packageDir,
318
+ };
297
319
  }
298
- cached = readAgentsBundleFromFs(process.cwd(), workspaceSource);
299
- return cached;
320
+ // coercion-ok: workspace-core discovery is optional in edge runtimes.
300
321
  }
301
322
  catch {
302
- cached = EMPTY;
303
- return cached;
323
+ // workspace-core discovery isn't available (e.g. edge runtime).
304
324
  }
325
+ const { createAgentNativeConfigContext, loadResolvedAgentNativeConfig } = await import("../vite/agent-native-config-loader.js");
326
+ const production = process.env.NODE_ENV === "production";
327
+ const config = await loadResolvedAgentNativeConfig(process.cwd(), createAgentNativeConfigContext(production ? "build" : "serve", production ? "production" : "development"));
328
+ cached = readAgentsBundleFromFs(process.cwd(), workspaceSource, {
329
+ instructions: config.instructions,
330
+ });
331
+ return cached;
305
332
  }
306
333
  /**
307
334
  * Generate the `<skills>` block to inject into the system prompt.
@@ -1,10 +1,15 @@
1
1
  import { autoMountAuth } from "./auth.js";
2
+ import { runBetterAuthMigrations } from "./better-auth-migrations.js";
2
3
  import { getH3App, awaitBootstrap, markDefaultPluginProvided, trackPluginInit, } from "./framework-request-handler.js";
3
4
  export function createAuthPlugin(options) {
4
5
  return (nitroApp) => {
5
6
  markDefaultPluginProvided(nitroApp, "auth");
6
7
  const initPromise = (async () => {
7
8
  await awaitBootstrap(nitroApp);
9
+ // guard:allow-boot-data-work — local/long-lived runtimes provision auth
10
+ // before mounting routes; production functions are rejected by the
11
+ // migration runner and use the release job instead.
12
+ await runBetterAuthMigrations(nitroApp);
8
13
  await autoMountAuth(getH3App(nitroApp), options);
9
14
  })();
10
15
  trackPluginInit(nitroApp, initPromise, {
@@ -16,8 +16,7 @@ import { pgTable, text as pgText, timestamp as pgTimestamp, boolean as pgBoolean
16
16
  import { sqliteTable, text as sqliteText, integer as sqliteInteger, } from "drizzle-orm/sqlite-core";
17
17
  import { TEMPLATES } from "../cli/templates-meta.js";
18
18
  import { getDbExec, isPostgres } from "../db/client.js";
19
- import { getDialect, getDatabaseUrl, getDatabaseAuthToken, closePgliteClients, getPgliteClient, isPgliteUrl, loadPgliteDrizzle, pgPoolOptions, neonPoolOptions, attachNeonPoolErrorLogger, sharedDbPool, onSharedDbPoolsClosed, onSharedDbPoolReplaced, } from "../db/client.js";
20
- import { ensureTableExists } from "../db/ddl-guard.js";
19
+ import { getDialect, getDatabaseUrl, getDatabaseAuthToken, closePgliteClients, getPgliteClient, isPgliteUrl, loadPgliteDrizzle, pgPoolOptions, neonPoolOptions, guardNeonPool, sharedDbPool, onSharedDbPoolsClosed, onSharedDbPoolReplaced, } from "../db/client.js";
21
20
  import { CORE_RESET_PASSWORD_EMAIL_ID, CORE_VERIFY_SIGNUP_EMAIL_ID, } from "../email-catalog/system-emails.js";
22
21
  import { saveOAuthTokens } from "../oauth-tokens/store.js";
23
22
  import { acceptPendingInvitationsForEmail } from "../org/accept-pending.js";
@@ -518,65 +517,6 @@ async function mirrorGoogleAccountToOAuthTokens(account) {
518
517
  tokens.id_token = account.idToken;
519
518
  await saveOAuthTokens("google", email, tokens, email);
520
519
  }
521
- async function ensureBetterAuthTables() {
522
- const db = getDbExec();
523
- // PG guard: probe information_schema first (no lock) for each table; run
524
- // DDL only when missing, bounded by a transaction-scoped lock_timeout.
525
- // Probe names are UNQUOTED (what information_schema.tables.table_name stores);
526
- // createSql keeps the QUOTED "user"/"session"/… form required by Postgres.
527
- if (isPostgres()) {
528
- const pgTables = [
529
- [
530
- "user",
531
- `CREATE TABLE IF NOT EXISTS "user" (id TEXT PRIMARY KEY, name TEXT NOT NULL, email TEXT NOT NULL UNIQUE, email_verified BOOLEAN NOT NULL DEFAULT FALSE, image TEXT, created_at TIMESTAMPTZ NOT NULL, updated_at TIMESTAMPTZ NOT NULL)`,
532
- ],
533
- [
534
- "session",
535
- `CREATE TABLE IF NOT EXISTS "session" (id TEXT PRIMARY KEY, expires_at TIMESTAMPTZ NOT NULL, token TEXT NOT NULL UNIQUE, created_at TIMESTAMPTZ NOT NULL, updated_at TIMESTAMPTZ NOT NULL, ip_address TEXT, user_agent TEXT, user_id TEXT NOT NULL, active_organization_id TEXT)`,
536
- ],
537
- [
538
- "account",
539
- `CREATE TABLE IF NOT EXISTS "account" (id TEXT PRIMARY KEY, account_id TEXT NOT NULL, provider_id TEXT NOT NULL, user_id TEXT NOT NULL, access_token TEXT, refresh_token TEXT, id_token TEXT, access_token_expires_at TIMESTAMPTZ, refresh_token_expires_at TIMESTAMPTZ, scope TEXT, password TEXT, created_at TIMESTAMPTZ NOT NULL, updated_at TIMESTAMPTZ NOT NULL)`,
540
- ],
541
- [
542
- "verification",
543
- `CREATE TABLE IF NOT EXISTS "verification" (id TEXT PRIMARY KEY, identifier TEXT NOT NULL, value TEXT NOT NULL, expires_at TIMESTAMPTZ NOT NULL, created_at TIMESTAMPTZ NOT NULL, updated_at TIMESTAMPTZ NOT NULL)`,
544
- ],
545
- [
546
- "organization",
547
- `CREATE TABLE IF NOT EXISTS "organization" (id TEXT PRIMARY KEY, name TEXT NOT NULL, slug TEXT NOT NULL UNIQUE, logo TEXT, metadata TEXT, created_at TIMESTAMPTZ NOT NULL, updated_at TIMESTAMPTZ NOT NULL)`,
548
- ],
549
- [
550
- "member",
551
- `CREATE TABLE IF NOT EXISTS "member" (id TEXT PRIMARY KEY, organization_id TEXT NOT NULL, user_id TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'member', created_at TIMESTAMPTZ NOT NULL, updated_at TIMESTAMPTZ NOT NULL)`,
552
- ],
553
- [
554
- "invitation",
555
- `CREATE TABLE IF NOT EXISTS "invitation" (id TEXT PRIMARY KEY, organization_id TEXT NOT NULL, email TEXT NOT NULL, role TEXT, status TEXT NOT NULL DEFAULT 'pending', expires_at TIMESTAMPTZ NOT NULL, inviter_id TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL, updated_at TIMESTAMPTZ NOT NULL)`,
556
- ],
557
- [
558
- "jwks",
559
- `CREATE TABLE IF NOT EXISTS "jwks" (id TEXT PRIMARY KEY, public_key TEXT NOT NULL, private_key TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL, expires_at TIMESTAMPTZ)`,
560
- ],
561
- ];
562
- for (const [name, sql] of pgTables)
563
- await ensureTableExists(name, sql);
564
- return;
565
- }
566
- // SQLite (local dev): no lock problem — keep the original behaviour.
567
- const sqliteStatements = [
568
- `CREATE TABLE IF NOT EXISTS user (id TEXT PRIMARY KEY, name TEXT NOT NULL, email TEXT NOT NULL UNIQUE, email_verified INTEGER NOT NULL DEFAULT 0, image TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL)`,
569
- `CREATE TABLE IF NOT EXISTS session (id TEXT PRIMARY KEY, expires_at INTEGER NOT NULL, token TEXT NOT NULL UNIQUE, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, ip_address TEXT, user_agent TEXT, user_id TEXT NOT NULL, active_organization_id TEXT)`,
570
- `CREATE TABLE IF NOT EXISTS account (id TEXT PRIMARY KEY, account_id TEXT NOT NULL, provider_id TEXT NOT NULL, user_id TEXT NOT NULL, access_token TEXT, refresh_token TEXT, id_token TEXT, access_token_expires_at INTEGER, refresh_token_expires_at INTEGER, scope TEXT, password TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL)`,
571
- `CREATE TABLE IF NOT EXISTS verification (id TEXT PRIMARY KEY, identifier TEXT NOT NULL, value TEXT NOT NULL, expires_at INTEGER NOT NULL, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL)`,
572
- `CREATE TABLE IF NOT EXISTS organization (id TEXT PRIMARY KEY, name TEXT NOT NULL, slug TEXT NOT NULL UNIQUE, logo TEXT, metadata TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL)`,
573
- `CREATE TABLE IF NOT EXISTS member (id TEXT PRIMARY KEY, organization_id TEXT NOT NULL, user_id TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'member', created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL)`,
574
- `CREATE TABLE IF NOT EXISTS invitation (id TEXT PRIMARY KEY, organization_id TEXT NOT NULL, email TEXT NOT NULL, role TEXT, status TEXT NOT NULL DEFAULT 'pending', expires_at INTEGER NOT NULL, inviter_id TEXT NOT NULL, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL)`,
575
- `CREATE TABLE IF NOT EXISTS jwks (id TEXT PRIMARY KEY, public_key TEXT NOT NULL, private_key TEXT NOT NULL, created_at INTEGER NOT NULL, expires_at INTEGER)`,
576
- ];
577
- for (const sql of sqliteStatements)
578
- await db.execute(sql);
579
- }
580
520
  /**
581
521
  * Get or create the Better Auth instance.
582
522
  * Lazily initialized on first call — the database must be reachable by then.
@@ -860,7 +800,6 @@ function resetAuthOnPoolClose(driver, url) {
860
800
  async function createBetterAuthInstance(config) {
861
801
  const dialect = getDialect();
862
802
  const basePath = config?.basePath ?? "/_agent-native/auth/ba";
863
- await ensureBetterAuthTables();
864
803
  // Build social providers from env vars
865
804
  const socialProviders = {
866
805
  ...config?.socialProviders,
@@ -1212,7 +1151,7 @@ async function buildDatabaseConfig(dialect) {
1212
1151
  // connections reached" across concurrent serverless instances.
1213
1152
  resetAuthOnPoolClose("neon", url);
1214
1153
  _neonAuthPool = sharedDbPool("neon", url, () => new Pool({ connectionString: url, ...neonPoolOptions() }));
1215
- attachNeonPoolErrorLogger(_neonAuthPool, "db/neon-auth");
1154
+ guardNeonPool(_neonAuthPool, url, "db/neon-auth");
1216
1155
  const { drizzle } = await import("drizzle-orm/neon-serverless");
1217
1156
  const db = drizzle(buildResilientNeonPool(_neonAuthPool), {
1218
1157
  schema: pgAuthSchema,