@agent-native/core 0.145.0 → 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.
- package/dist/agent/run-manager.d.ts +44 -1
- package/dist/agent/run-manager.js +70 -8
- package/dist/chat-threads/store.js +6 -4
- package/dist/client/use-db-sync.js +9 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/ddl-guard.d.ts +8 -0
- package/dist/db/ddl-guard.js +148 -0
- package/dist/deploy/build.d.ts +36 -0
- package/dist/deploy/build.js +78 -5
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/accept-pending.js +2 -2
- package/dist/org/auth-policy.js +4 -0
- package/dist/org/auto-join-domain.d.ts +9 -0
- package/dist/org/auto-join-domain.js +53 -4
- package/dist/org/context.js +12 -3
- package/dist/org/handlers.js +17 -5
- package/dist/org/request-org-cache.d.ts +24 -2
- package/dist/org/request-org-cache.js +57 -2
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/provider-api/actions/provider-api.d.ts +6 -6
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/resources/store.d.ts +1 -1
- package/dist/resources/store.js +96 -7
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-chat-plugin.js +16 -4
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/auth.d.ts +3 -0
- package/dist/server/auth.js +22 -1
- package/dist/server/collab-plugin.js +10 -4
- package/dist/server/core-routes-plugin.js +3 -0
- package/dist/server/session-email-cache.d.ts +14 -0
- package/dist/server/session-email-cache.js +48 -0
- package/dist/server/sweep-runtime.d.ts +22 -0
- package/dist/server/sweep-runtime.js +28 -0
- package/dist/settings/store.js +63 -7
- package/dist/shared/ttl-cache.d.ts +59 -0
- package/dist/shared/ttl-cache.js +43 -0
- package/dist/sharing/actions/list-resource-shares.d.ts +3 -3
- package/dist/sharing/actions/list-resource-shares.js +4 -1
- package/dist/triggers/condition-evaluator.js +11 -27
- package/docs/content/deployment.mdx +48 -0
- package/docs/content/environment-variables.mdx +5 -0
- package/package.json +3 -3
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded process-level TTL cache for answers that are expensive to re-fetch
|
|
3
|
+
* and safe to serve slightly stale.
|
|
4
|
+
*
|
|
5
|
+
* ## Which cache do I want?
|
|
6
|
+
*
|
|
7
|
+
* This repo has exactly two general caching patterns. Reach for an existing one
|
|
8
|
+
* rather than hand-rolling a third `Map` with timestamps in it:
|
|
9
|
+
*
|
|
10
|
+
* 1. **Request-scoped** — `WeakMap<RequestContext, Map<...>>`, freed with the
|
|
11
|
+
* request. Use when repeated reads within ONE request must collapse but no
|
|
12
|
+
* answer may outlive it. See `settings/store.ts` (`requestSettingsCache`),
|
|
13
|
+
* `org/request-org-cache.ts`, `secrets/storage.ts`.
|
|
14
|
+
* 2. **Process-scoped with a TTL** — this module. Use when every request
|
|
15
|
+
* re-reads the same value and staleness bounded by the TTL is acceptable.
|
|
16
|
+
* Every consumer must also wire an invalidation path for the writes that
|
|
17
|
+
* change the answer; the TTL is a backstop, not the correctness story.
|
|
18
|
+
*
|
|
19
|
+
* Two caches deliberately do NOT use this and should stay as they are, because
|
|
20
|
+
* flattening them into this shape would lose behavior they depend on:
|
|
21
|
+
*
|
|
22
|
+
* - `server/poll.ts`'s collab access cache — different TTL per outcome
|
|
23
|
+
* (allow vs deny), a per-resource invalidation epoch, and in-flight request
|
|
24
|
+
* dedup.
|
|
25
|
+
* - `demo/redact.ts` — a bidirectional memo (forward map plus a produced-value
|
|
26
|
+
* reverse index) with refresh-on-read recency, needed for round-trip
|
|
27
|
+
* stability.
|
|
28
|
+
*
|
|
29
|
+
* The per-request memos elsewhere in this codebase (`event.context` caches,
|
|
30
|
+
* `requestSettingsCache`) collapse repeated reads WITHIN one request. They do
|
|
31
|
+
* nothing for a value every request re-reads identically — a session token's
|
|
32
|
+
* email, an account's org memberships — which on a remote Postgres is a round
|
|
33
|
+
* trip per request per value, forever.
|
|
34
|
+
*
|
|
35
|
+
* ## Only cache successful reads
|
|
36
|
+
*
|
|
37
|
+
* Never `set` a value that stands for "I could not read this". A cached
|
|
38
|
+
* "unreadable" is indistinguishable from a cached "absent" to every later
|
|
39
|
+
* caller, which is exactly how a transient blip turns into a
|
|
40
|
+
* permanent-looking wrong answer. Leave failures on the uncached path so they
|
|
41
|
+
* stay loud and retryable.
|
|
42
|
+
*
|
|
43
|
+
* ## Bounded on purpose
|
|
44
|
+
*
|
|
45
|
+
* Keys here are user-supplied (session tokens, emails), so an unbounded map is
|
|
46
|
+
* a memory leak that grows with traffic. `maxEntries` evicts oldest-written
|
|
47
|
+
* first once the cap is reached.
|
|
48
|
+
*/
|
|
49
|
+
export interface TtlCache<V> {
|
|
50
|
+
get(key: string): V | undefined;
|
|
51
|
+
set(key: string, value: V): void;
|
|
52
|
+
delete(key: string): void;
|
|
53
|
+
clear(): void;
|
|
54
|
+
readonly size: number;
|
|
55
|
+
}
|
|
56
|
+
export declare function createTtlCache<V>(options: {
|
|
57
|
+
ttlMs: number;
|
|
58
|
+
maxEntries: number;
|
|
59
|
+
}): TtlCache<V>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export function createTtlCache(options) {
|
|
2
|
+
const { ttlMs, maxEntries } = options;
|
|
3
|
+
if (!(ttlMs > 0)) {
|
|
4
|
+
throw new Error(`createTtlCache: ttlMs must be positive, got ${ttlMs}`);
|
|
5
|
+
}
|
|
6
|
+
if (!(maxEntries > 0)) {
|
|
7
|
+
throw new Error(`createTtlCache: maxEntries must be positive, got ${maxEntries}`);
|
|
8
|
+
}
|
|
9
|
+
const entries = new Map();
|
|
10
|
+
return {
|
|
11
|
+
get(key) {
|
|
12
|
+
const hit = entries.get(key);
|
|
13
|
+
if (!hit)
|
|
14
|
+
return undefined;
|
|
15
|
+
if (hit.expiresAt <= Date.now()) {
|
|
16
|
+
entries.delete(key);
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
return hit.value;
|
|
20
|
+
},
|
|
21
|
+
set(key, value) {
|
|
22
|
+
// Delete before insert so Map insertion order tracks the newest write,
|
|
23
|
+
// which is what the eviction loop below reads as "oldest".
|
|
24
|
+
entries.delete(key);
|
|
25
|
+
entries.set(key, { value, expiresAt: Date.now() + ttlMs });
|
|
26
|
+
while (entries.size > maxEntries) {
|
|
27
|
+
const oldest = entries.keys().next();
|
|
28
|
+
if (oldest.done)
|
|
29
|
+
break;
|
|
30
|
+
entries.delete(oldest.value);
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
delete(key) {
|
|
34
|
+
entries.delete(key);
|
|
35
|
+
},
|
|
36
|
+
clear() {
|
|
37
|
+
entries.clear();
|
|
38
|
+
},
|
|
39
|
+
get size() {
|
|
40
|
+
return entries.size;
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -12,9 +12,9 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
12
12
|
orgId?: undefined;
|
|
13
13
|
role?: undefined;
|
|
14
14
|
} | {
|
|
15
|
-
ownerEmail:
|
|
16
|
-
orgId:
|
|
17
|
-
visibility:
|
|
15
|
+
ownerEmail: string;
|
|
16
|
+
orgId: string;
|
|
17
|
+
visibility: import("../schema.js").Visibility;
|
|
18
18
|
role: "owner" | import("../schema.js").ShareRole;
|
|
19
19
|
shares: any;
|
|
20
20
|
policy: {
|
|
@@ -43,7 +43,10 @@ export default defineAction({
|
|
|
43
43
|
allowPublic: reg.allowPublic !== false,
|
|
44
44
|
requireOrgMemberForUserShares: reg.requireOrgMemberForUserShares === true,
|
|
45
45
|
};
|
|
46
|
-
|
|
46
|
+
// Only `ownerEmail`/`orgId`/`visibility` are read below, all of which the
|
|
47
|
+
// projected load carries — so the share dialog never pulls a resource's
|
|
48
|
+
// body blob just to render who it is shared with.
|
|
49
|
+
const access = await resolveAccess(args.resourceType, args.resourceId, undefined, { skipResourceBody: true });
|
|
47
50
|
if (!access)
|
|
48
51
|
return { ownerEmail: null, visibility: null, shares: [], policy };
|
|
49
52
|
const db = reg.getDb();
|
|
@@ -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
|
-
//
|
|
24
|
-
|
|
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
|
|
74
|
-
return cached
|
|
75
|
-
}
|
|
59
|
+
if (cached !== undefined)
|
|
60
|
+
return cached;
|
|
76
61
|
const result = await callHaikuClassifier(condition, payload, apiKey);
|
|
77
|
-
|
|
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
|
|
|
@@ -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. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.145.
|
|
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": {
|
|
@@ -412,8 +412,8 @@
|
|
|
412
412
|
"y-protocols": "^1.0.7",
|
|
413
413
|
"yjs": "^13.6.31",
|
|
414
414
|
"zod": "^4.3.6",
|
|
415
|
-
"@agent-native/
|
|
416
|
-
"@agent-native/
|
|
415
|
+
"@agent-native/toolkit": "^0.13.3",
|
|
416
|
+
"@agent-native/recap-cli": "0.5.3"
|
|
417
417
|
},
|
|
418
418
|
"devDependencies": {
|
|
419
419
|
"@ai-sdk/anthropic": "^3.0.71",
|