@agent-native/core 0.144.3 → 0.145.1

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 (71) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/clips/changelog/2026-08-06-desktop-full-screen-recordings-now-normalize-microphone-leve.md +6 -0
  3. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +185 -69
  4. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +47 -4
  5. package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -1
  6. package/corpus/templates/slides/server/plugins/agent-chat.ts +1 -1
  7. package/dist/agent/production-agent.d.ts +6 -0
  8. package/dist/agent/run-manager.d.ts +44 -1
  9. package/dist/agent/run-manager.js +70 -8
  10. package/dist/chat-threads/store.js +6 -4
  11. package/dist/client/use-db-sync.js +9 -1
  12. package/dist/collab/awareness.d.ts +2 -2
  13. package/dist/collab/struct-routes.d.ts +1 -1
  14. package/dist/db/ddl-guard.d.ts +8 -0
  15. package/dist/db/ddl-guard.js +148 -0
  16. package/dist/deploy/build.d.ts +36 -0
  17. package/dist/deploy/build.js +78 -5
  18. package/dist/framework-tools.d.ts +126 -0
  19. package/dist/framework-tools.js +114 -0
  20. package/dist/notifications/routes.d.ts +3 -3
  21. package/dist/org/accept-pending.js +2 -2
  22. package/dist/org/auth-policy.js +4 -0
  23. package/dist/org/auto-join-domain.d.ts +9 -0
  24. package/dist/org/auto-join-domain.js +53 -4
  25. package/dist/org/context.js +12 -3
  26. package/dist/org/handlers.js +17 -5
  27. package/dist/org/request-org-cache.d.ts +24 -2
  28. package/dist/org/request-org-cache.js +57 -2
  29. package/dist/provider-api/actions/custom-provider-registration.d.ts +6 -6
  30. package/dist/provider-api/actions/provider-api.d.ts +6 -6
  31. package/dist/resources/store.d.ts +1 -1
  32. package/dist/resources/store.js +96 -7
  33. package/dist/secrets/routes.d.ts +9 -9
  34. package/dist/server/action-discovery.d.ts +27 -0
  35. package/dist/server/action-discovery.js +89 -0
  36. package/dist/server/agent-chat/action-filters-a2a.d.ts +11 -0
  37. package/dist/server/agent-chat/action-filters-a2a.js +17 -1
  38. package/dist/server/agent-chat/framework-prompts.d.ts +2 -0
  39. package/dist/server/agent-chat/plugin-options.d.ts +30 -0
  40. package/dist/server/agent-chat/prompt-resources.d.ts +4 -1
  41. package/dist/server/agent-chat/prompt-resources.js +8 -2
  42. package/dist/server/agent-chat-plugin.js +138 -75
  43. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  44. package/dist/server/auth.d.ts +3 -0
  45. package/dist/server/auth.js +22 -1
  46. package/dist/server/collab-plugin.js +10 -4
  47. package/dist/server/core-routes-plugin.js +3 -0
  48. package/dist/server/prompts/framework-core-compact.d.ts +5 -0
  49. package/dist/server/prompts/framework-core-compact.js +28 -12
  50. package/dist/server/prompts/framework-core.d.ts +5 -0
  51. package/dist/server/prompts/framework-core.js +33 -16
  52. package/dist/server/prompts/index.d.ts +1 -1
  53. package/dist/server/prompts/index.js +1 -1
  54. package/dist/server/prompts/shared-rules.d.ts +12 -4
  55. package/dist/server/prompts/shared-rules.js +14 -4
  56. package/dist/server/session-email-cache.d.ts +14 -0
  57. package/dist/server/session-email-cache.js +48 -0
  58. package/dist/server/sweep-runtime.d.ts +22 -0
  59. package/dist/server/sweep-runtime.js +28 -0
  60. package/dist/settings/store.js +63 -7
  61. package/dist/shared/ttl-cache.d.ts +59 -0
  62. package/dist/shared/ttl-cache.js +43 -0
  63. package/dist/sharing/actions/list-resource-shares.d.ts +3 -3
  64. package/dist/sharing/actions/list-resource-shares.js +4 -1
  65. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -3
  66. package/dist/triggers/condition-evaluator.js +11 -27
  67. package/docs/content/deployment.mdx +95 -13
  68. package/docs/content/environment-variables.mdx +5 -0
  69. package/docs/content/key-concepts.mdx +13 -6
  70. package/package.json +1 -1
  71. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -3
@@ -217,9 +217,12 @@ POST /_agent-native/extensions
217
217
 
218
218
  HTTP creation is disabled by default. The host app must set
219
219
  `extensionTools: true` on `createCoreRoutesPlugin()` as well as
220
- `createAgentChatPlugin()`; otherwise authenticated collection `POST` requests
221
- return `403` while existing extension runtime, read, edit, and deep-link routes
222
- remain available for compatibility.
220
+ `frameworkTools: { extensions: true }` on `createAgentChatPlugin()`; otherwise
221
+ authenticated collection `POST` requests return `403` while existing extension
222
+ runtime, read, edit, and deep-link routes remain available for compatibility.
223
+ (`extensionTools` on the agent-chat plugin is the deprecated spelling of
224
+ `frameworkTools.extensions`; the core-routes option keeps its own name because
225
+ it gates route mounting rather than agent tools.)
223
226
 
224
227
  The action accepts:
225
228
 
@@ -14,16 +14,22 @@
14
14
  * invalidated wholesale by bumping CONDITION_EVAL_VERSION.
15
15
  */
16
16
  import { createHash } from "node:crypto";
17
+ import { createTtlCache } from "../shared/ttl-cache.js";
17
18
  /**
18
19
  * Bumped whenever the prompt template, model, or hardening logic changes.
19
20
  * Included in the cache key so cached "yes" answers from a previous
20
21
  * (potentially weaker) prompt don't satisfy conditions in the new prompt.
21
22
  */
22
23
  const CONDITION_EVAL_VERSION = "v2";
23
- // LRU cache: hash → { result: boolean, expiresAt: number }
24
- const _cache = new Map();
24
+ // Bounded TTL cache: hash → classifier result. Uses the shared primitive so
25
+ // there is one implementation of "expire and cap an in-memory map" rather than
26
+ // one per call site; see `shared/ttl-cache.ts` for which pattern to use where.
25
27
  const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
26
28
  const MAX_CACHE_SIZE = 500;
29
+ const _cache = createTtlCache({
30
+ ttlMs: CACHE_TTL_MS,
31
+ maxEntries: MAX_CACHE_SIZE,
32
+ });
27
33
  function cacheKey(condition, payload) {
28
34
  // Salt the cache key with the prompt version + a separate hash of the
29
35
  // payload so two callers can't cross-pollute each other's cache via
@@ -41,26 +47,6 @@ function cacheKey(condition, payload) {
41
47
  const raw = `${CONDITION_EVAL_VERSION}|${condition}|${payloadHash}`;
42
48
  return createHash("sha256").update(raw).digest("hex").slice(0, 32);
43
49
  }
44
- function pruneCache() {
45
- if (_cache.size <= MAX_CACHE_SIZE)
46
- return;
47
- const now = Date.now();
48
- for (const [key, entry] of _cache) {
49
- if (entry.expiresAt < now)
50
- _cache.delete(key);
51
- }
52
- // If still too large, drop oldest entries
53
- if (_cache.size > MAX_CACHE_SIZE) {
54
- const excess = _cache.size - MAX_CACHE_SIZE;
55
- let deleted = 0;
56
- for (const key of _cache.keys()) {
57
- if (deleted >= excess)
58
- break;
59
- _cache.delete(key);
60
- deleted++;
61
- }
62
- }
63
- }
64
50
  /**
65
51
  * Evaluate whether a natural-language condition matches an event payload.
66
52
  * Returns true if the condition is empty/undefined (unconditional trigger).
@@ -70,12 +56,10 @@ export async function evaluateCondition(condition, payload, apiKey) {
70
56
  return true;
71
57
  const key = cacheKey(condition, payload);
72
58
  const cached = _cache.get(key);
73
- if (cached && cached.expiresAt > Date.now()) {
74
- return cached.result;
75
- }
59
+ if (cached !== undefined)
60
+ return cached;
76
61
  const result = await callHaikuClassifier(condition, payload, apiKey);
77
- pruneCache();
78
- _cache.set(key, { result, expiresAt: Date.now() + CACHE_TTL_MS });
62
+ _cache.set(key, result);
79
63
  return result;
80
64
  }
81
65
  async function callHaikuClassifier(condition, payload, apiKey) {
@@ -433,6 +433,49 @@ npx @agent-native/core@latest deploy --preset netlify
433
433
 
434
434
  The workspace build writes static assets under `dist/_workspace_static/` and routes each app to its own Netlify function without forced asset redirects, so files like `/mail/assets/...` are served statically before the server function handles app routes.
435
435
 
436
+ ### Keep-warm and scale-to-zero databases {#netlify-keep-warm}
437
+
438
+ The Netlify build emits a scheduled function that requests `/_agent-native/health` **every minute**. That keeps the server function and its database warm so the next visitor after an idle period doesn't pay a cold start (1–5s on Neon). On provisioned compute this is the right default.
439
+
440
+ **On a metered scale-to-zero database it is the wrong default.** A once-a-minute wake means autosuspend never fires, so the database bills and quota-limits as though it were awake continuously with nobody using the app. On a free-tier Neon this exhausts the compute quota, and the database then rejects **all** reads mid-session — the symptom is a dead app, not a slow one.
441
+
442
+ Three knobs, all opt-in, defaults unchanged:
443
+
444
+ | Variable | Effect |
445
+ | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
446
+ | `AGENT_NATIVE_DISABLE_KEEP_WARM` | Skips the scheduled function entirely. The database is free to autosuspend; the next visitor after an idle period pays its cold start. |
447
+ | `AGENT_NATIVE_KEEP_WARM_SCHEDULE` | Overrides the cadence with a 5-field cron expression, e.g. `*/5 * * * *`. An unparseable value **fails the build** rather than silently reverting to once a minute. |
448
+ | `AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND` | Drops only the background-function warm, keeping the server warm. Warming `server` is one request; warming `-background` starts a fresh container that re-probes the schema. |
449
+
450
+ If you are on a free or otherwise quota-limited database tier, set `AGENT_NATIVE_DISABLE_KEEP_WARM=1` or pick a slower cadence.
451
+
452
+ ### On-demand schema DDL {#skip-ensure-tables}
453
+
454
+ Each store calls `ensureTable()` on its first database touch, which probes
455
+ `information_schema` / `pg_indexes` and issues `CREATE TABLE` / `ADD COLUMN` /
456
+ `CREATE INDEX` only for what is genuinely missing. On a long-lived Node server
457
+ that cost is paid once per boot and is invisible. On serverless, "first touch" is
458
+ **every cold start**, across ~57 stores — so a cold request can pay a few hundred
459
+ serial round trips before it does any real work.
460
+
461
+ Two things reduce it:
462
+
463
+ - The probes are answered from **one batched introspection pass per database**
464
+ (two queries), instead of one query per table, column, and index. This is
465
+ automatic and needs no configuration.
466
+ - `AGENT_NATIVE_SKIP_ENSURE_TABLES=1` skips the probe-and-DDL machinery
467
+ altogether, which is the largest cold-start latency win available.
468
+
469
+ Set `AGENT_NATIVE_SKIP_ENSURE_TABLES=1` when your database schema is already
470
+ migrated and you do not want application boot creating or altering tables — the
471
+ normal case for a production deployment with a real migration step.
472
+
473
+ <Callout tone="risk">
474
+
475
+ **This flag does not and cannot fail closed.** If the schema is in fact missing, the first real query fails loudly rather than being repaired on the fly — which is the point, but it means you own the migration story. Do not set it on a deployment that relies on application boot to provision its tables.
476
+
477
+ </Callout>
478
+
436
479
  ## Cloudflare Pages {#cloudflare-pages}
437
480
 
438
481
  ```ts filename="vite.config.ts"
@@ -532,6 +575,11 @@ hosting behavior.
532
575
  | `APP_URL` | Optional canonical public origin. Checked ahead of `BETTER_AUTH_URL` when resolving the A2A JWT audience, the OAuth public origin, self-dispatch webhook targets, and generated resource links. Set it explicitly on preview/staging deploys where the request host is unreliable. |
533
576
  | `AGENT_PROD_CODE_EXECUTION` | Optional production code-execution mode: `off` (default), `sandboxed`, or `trusted`. See [Production Code Execution](#production-code-execution). |
534
577
  | `AGENT_NATIVE_SSR_CACHE` | Deployment-wide SSR shell cache policy: unset/`on` keeps the default hard-cache, `off` sends `no-store`, or a duration such as `30s` / `5m` sets a shorter freshness. See [SSR Caching](#ssr-caching). |
578
+ | `AGENT_NATIVE_DISABLE_KEEP_WARM` | Skip the Netlify keep-warm scheduled function so a scale-to-zero database can autosuspend. See [Keep-warm](#netlify-keep-warm). |
579
+ | `AGENT_NATIVE_KEEP_WARM_SCHEDULE` | Override the keep-warm cadence with a 5-field cron expression (default `* * * * *`). An unparseable value fails the build. See [Keep-warm](#netlify-keep-warm). |
580
+ | `AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND` | Drop only the background-function warm and keep the server warm. See [Keep-warm](#netlify-keep-warm). |
581
+ | `AGENT_NATIVE_DISABLE_INPROCESS_SWEEPS` | Turn off the in-process backstop sweep timers (automation redispatch, agent-teams reconciliation, sandbox-execution recovery). On serverless these run per warm container, so their query rate scales with instance count. Set it **only** where a durable scheduler already drives the same recovery, or queued work will not be retried. |
582
+ | `AGENT_NATIVE_SKIP_ENSURE_TABLES` | Skip on-demand schema DDL entirely. Removes the schema-probe round trips every cold start pays before doing any work. Requires that your schema is already migrated — see [On-demand schema DDL](#skip-ensure-tables). |
535
583
  | `AGENT_NATIVE_BUILDER_RELAY_SECRET` | Dedicated 32+ char shared HMAC secret for preview-safe Builder authorization relay. Set the same value on the approved corporate callback deployment and preview deployments only when authorization must land in an isolated preview database. |
536
584
  | `AGENT_NATIVE_BUILDER_RELAY_TARGET_ORIGINS` | Corporate callback-only, comma-separated allowlist of exact trusted preview origins (for example, `https://0123456789abcdef01234567--content.netlify.app`). Set it only on the corporate callback deployment. Netlify origins must use an immutable, deploy-specific 24-hex permalink; mutable `deploy-preview-*` aliases, wildcards, and domain suffixes are rejected. |
537
585
 
@@ -580,16 +628,19 @@ Rotate signing/session keys by replacing the env var on every instance and redep
580
628
 
581
629
  ## Production Agent Tools {#production-agent-tools}
582
630
 
583
- Production agents get the app's registered actions plus framework tools from
584
- the agent chat plugin. SQL inspection is enabled by default, while database
585
- writes go through typed app actions unless the app explicitly opts into raw
586
- write tools:
631
+ Production agents get the app's registered actions plus the framework's own
632
+ tools. `frameworkTools` selects which of those framework tools this app exposes.
633
+ Every group defaults to today's behavior, so omitting the option changes
634
+ nothing:
587
635
 
588
636
  ```ts filename="server/plugins/agent-chat.ts"
589
637
  export default createAgentChatPlugin({
590
- // Default: "read"
591
- databaseTools: "read", // "write" | "read" | "off"
592
- extensionTools: true,
638
+ frameworkTools: {
639
+ database: "read", // "write" | "read" | "off" — default "read"
640
+ extensions: true, // default false
641
+ sharing: false, // this app has no share surface
642
+ review: false,
643
+ },
593
644
  });
594
645
  ```
595
646
 
@@ -599,17 +650,48 @@ export default createCoreRoutesPlugin({
599
650
  });
600
651
  ```
601
652
 
602
- - `databaseTools: "read"` — default. Registers only `db-schema` and `db-query`;
653
+ `database` and `extensions` accept the values the old top-level flags did:
654
+
655
+ - `database: "read"` — default. Registers only `db-schema` and `db-query`;
603
656
  agents inspect data with SQL but must use typed app actions for writes.
604
- - `databaseTools: "write"` or `true` — additionally registers `db-exec` and
657
+ - `database: "write"` or `true` — additionally registers `db-exec` and
605
658
  `db-patch` for deliberate raw SQL maintenance. Writes are scoped to the
606
659
  current user/org and schema changes are blocked.
607
- - `databaseTools: "off"` or `false` — removes raw database tools from the
660
+ - `database: "off"` or `false` — removes raw database tools from the
608
661
  agent surface so the app's actions are the only data access path.
609
- - `extensionTools: true` — opts the app into framework extension-management
662
+ - `extensions: true` — opts the app into framework extension-management
610
663
  actions and prompt guidance (`create-extension`, `update-extension`, etc.).
611
- Set it on both plugins to also allow authenticated REST creation. Extensions
612
- are disabled by default.
664
+ Set `extensionTools: true` on the core-routes plugin as well to allow
665
+ authenticated REST creation. Extensions are disabled by default.
666
+
667
+ The remaining groups are booleans, all on by default: `sharing`, `review`,
668
+ `history`, `featureFlags`, `localization`, `audit`, `contextXray`,
669
+ `userProfile`, `automation`, `docs`, `resources`, `web`, `workspaceApps`,
670
+ `chat`, and `email`. Use `frameworkTools: "minimal"` to turn every group off at
671
+ once for a voice-first or single-purpose app, or
672
+ `frameworkTools: { preset: "minimal", resources: true }` to keep just one — an
673
+ explicit group key always wins over the preset.
674
+
675
+ Switching a group off removes it from the **agent** surfaces only: interactive
676
+ chat, MCP, A2A, and background runs. The matching HTTP action routes stay
677
+ mounted, because the UI reaches them through client hooks — disabling `sharing`
678
+ must not 404 a share dialog that is still on screen. Weigh that parity cost
679
+ before using it: the framework's contract is that anything the UI can do the
680
+ agent can do, so `sharing: false` alongside a visible share button is a
681
+ deliberate break, and only makes sense when the app has no such surface at all.
682
+
683
+ Framework tools are no longer promoted into the first model request by default,
684
+ independent of this option. They stay in the searchable registry and load
685
+ through `tool-search`, or immediately if the app names them in
686
+ `initialToolNames`.
687
+
688
+ <Callout tone="warning">
689
+ The top-level `databaseTools` and `extensionTools` options are deprecated in
690
+ favor of `frameworkTools.database` and `frameworkTools.extensions`. They are
691
+ still honored, but setting a top-level flag and its `frameworkTools`
692
+ equivalent to conflicting values throws at plugin startup rather than booting
693
+ with a tool surface nobody chose.
694
+ </Callout>
613
695
 
614
696
  ## Production Code Execution {#production-code-execution}
615
697
 
@@ -47,6 +47,11 @@ deployment-specific values in the environment or scoped secret store.
47
47
  | `ACCESS_TOKEN` / `ACCESS_TOKENS` | Static bearer fallback for MCP and Connect clients. | One token or a delimited token list; these are not browser auth. |
48
48
  | `AGENT_PROD_CODE_EXECUTION` | Production code-execution policy. | `off`, `sandboxed`, or `trusted`. See [Production Code Execution](/docs/deployment#production-code-execution). |
49
49
  | `AGENT_NATIVE_SSR_CACHE` | Deployment-wide public SSR shell cache policy. | Unset/`on`, `off`, or a duration such as `30s` or `5m`. See [SSR Caching](/docs/deployment#ssr-caching). |
50
+ | `AGENT_NATIVE_DISABLE_KEEP_WARM` | Lets a scale-to-zero database autosuspend instead of being woken every minute. | `1`; see [Keep-warm](/docs/deployment#netlify-keep-warm). |
51
+ | `AGENT_NATIVE_KEEP_WARM_SCHEDULE` | Keep-warm cadence override. | A 5-field cron expression such as `*/5 * * * *`; an unparseable value fails the build. |
52
+ | `AGENT_NATIVE_DISABLE_KEEP_WARM_BACKGROUND` | Drops only the background-function warm and keeps the server warm. | `1`; see [Keep-warm](/docs/deployment#netlify-keep-warm). |
53
+ | `AGENT_NATIVE_DISABLE_INPROCESS_SWEEPS` | Turns off the in-process backstop sweep timers where a durable scheduler drives the same work. | `1`; queued work is not retried without another driver. |
54
+ | `AGENT_NATIVE_SKIP_ENSURE_TABLES` | Skips on-demand schema DDL for an already-migrated database. | `1`; see [On-demand schema DDL](/docs/deployment#skip-ensure-tables). You own migrations when this is set. |
50
55
  | `COOKIE_DOMAIN` | Shares auth cookies across same-database subdomains when explicitly configured. | A cookie domain. |
51
56
  | `CORS_ALLOWED_ORIGINS` | Cross-origin request allowlist. | A comma-separated list of exact origins. |
52
57
  | `WEBHOOK_BASE_URL` | Optional public base URL for self-callback and webhook targets. | An absolute public `http(s)` origin. |
@@ -254,12 +254,19 @@ pnpm action db-query --sql "SELECT * FROM forms"
254
254
  ```
255
255
 
256
256
  The production agent chat plugin defaults raw SQL tools to read-only
257
- (`databaseTools: "read"`), so agents inspect app-owned data with `db-schema` /
258
- `db-query` and perform writes through typed app actions. Set
259
- `databaseTools: "write"` (or `true`) only for deliberate maintenance surfaces
260
- that should also expose scoped `db-exec` / `db-patch`; set
261
- `databaseTools: "off"` / `false` to require typed app actions for all data
262
- access.
257
+ (`frameworkTools: { database: "read" }`), so agents inspect app-owned data with
258
+ `db-schema` / `db-query` and perform writes through typed app actions. Set
259
+ `database: "write"` (or `true`) only for deliberate maintenance surfaces that
260
+ should also expose scoped `db-exec` / `db-patch`; set `database: "off"` /
261
+ `false` to require typed app actions for all data access.
262
+
263
+ `frameworkTools` governs the rest of the framework's own tools the same way —
264
+ sharing, review comments, version history, feature flags, localization, audit,
265
+ context X-Ray, profile, automations, docs, resources, web, cross-app delegation,
266
+ chat, and email. See
267
+ [Production Agent Tools](/docs/deployment#production-agent-tools) for the full
268
+ list, the `"minimal"` preset, and why disabling a group leaves its HTTP routes
269
+ mounted.
263
270
 
264
271
  ## Agent chat bridge {#agent-chat-bridge}
265
272
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.144.3",
3
+ "version": "0.145.1",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -217,9 +217,12 @@ POST /_agent-native/extensions
217
217
 
218
218
  HTTP creation is disabled by default. The host app must set
219
219
  `extensionTools: true` on `createCoreRoutesPlugin()` as well as
220
- `createAgentChatPlugin()`; otherwise authenticated collection `POST` requests
221
- return `403` while existing extension runtime, read, edit, and deep-link routes
222
- remain available for compatibility.
220
+ `frameworkTools: { extensions: true }` on `createAgentChatPlugin()`; otherwise
221
+ authenticated collection `POST` requests return `403` while existing extension
222
+ runtime, read, edit, and deep-link routes remain available for compatibility.
223
+ (`extensionTools` on the agent-chat plugin is the deprecated spelling of
224
+ `frameworkTools.extensions`; the core-routes option keeps its own name because
225
+ it gates route mounting rather than agent tools.)
223
226
 
224
227
  The action accepts:
225
228