@agent-native/core 0.79.9 → 0.79.10

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/corpus/README.md CHANGED
@@ -28,4 +28,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core/corpus
28
28
  ## Generated Counts
29
29
 
30
30
  - core files: 2029
31
- - template files: 4373
31
+ - template files: 4374
@@ -1,5 +1,11 @@
1
1
  # @agent-native/core
2
2
 
3
+ ## 0.79.10
4
+
5
+ ### Patch Changes
6
+
7
+ - 7e19ed6: Return plain string action results with a JSON content type so browser action clients can parse successful responses.
8
+
3
9
  ## 0.79.9
4
10
 
5
11
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.79.9",
3
+ "version": "0.79.10",
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": {
@@ -356,12 +356,16 @@ export function mountActionRoutes(
356
356
  }
357
357
  }
358
358
 
359
- // If the action returned a string, try to parse as JSON for a clean response
359
+ // If the action returned a string, try to parse as JSON for a
360
+ // clean response. Plain strings still need to go over the HTTP
361
+ // action transport as JSON, otherwise H3 sends text/plain and the
362
+ // browser action client rejects the successful 2xx response.
360
363
  if (typeof result === "string") {
361
364
  try {
362
365
  return JSON.parse(result);
363
366
  } catch {
364
- return result;
367
+ setResponseHeader(event, "Content-Type", "application/json");
368
+ return JSON.stringify(result);
365
369
  }
366
370
  }
367
371
 
@@ -90,6 +90,17 @@ export function markExternalEmailRefresh() {
90
90
  externalRefreshAt = Date.now();
91
91
  }
92
92
 
93
+ export function consumeExternalEmailRefresh(): number | undefined {
94
+ const refreshAt = externalRefreshAt;
95
+ if (!refreshAt) return undefined;
96
+ if (Date.now() - refreshAt >= 5000) {
97
+ externalRefreshAt = 0;
98
+ return undefined;
99
+ }
100
+ externalRefreshAt = 0;
101
+ return refreshAt;
102
+ }
103
+
93
104
  function parseRecipients(value?: string): EmailMessage["to"] {
94
105
  return (value || "")
95
106
  .split(",")
@@ -501,8 +512,11 @@ export function useEmails(
501
512
  if (search) params.set("q", search);
502
513
  if (label) params.set("label", label);
503
514
  if (pageParam) params.set("pageToken", pageParam);
504
- if (externalRefreshAt && Date.now() - externalRefreshAt < 5000) {
505
- params.set("forceRefresh", String(externalRefreshAt));
515
+ const forceRefreshAt = !pageParam
516
+ ? consumeExternalEmailRefresh()
517
+ : undefined;
518
+ if (forceRefreshAt) {
519
+ params.set("forceRefresh", String(forceRefreshAt));
506
520
  }
507
521
  return apiFetch<EmailsPage>(`/api/emails?${params}`, { signal });
508
522
  },
@@ -682,6 +696,7 @@ export function useMarkThreadRead() {
682
696
  .map((e) => ({ id: e.id, accountEmail: e.accountEmail }));
683
697
  pendingByThread.current.set(threadId, unreadEntries);
684
698
  const unreadIds = unreadEntries.map((e) => e.id);
699
+ const previousThread = getCachedThread(threadId);
685
700
  // Set overrides so refetches don't revert read state
686
701
  for (const id of unreadIds) {
687
702
  setOptimisticOverride(id, { isRead: true });
@@ -694,13 +709,22 @@ export function useMarkThreadRead() {
694
709
  ),
695
710
  ),
696
711
  );
697
- return { previous, overrideIds: [...unreadIds] };
712
+ if (previousThread) {
713
+ setCachedThread(
714
+ threadId,
715
+ previousThread.map((message) => ({ ...message, isRead: true })),
716
+ );
717
+ }
718
+ return { previous, overrideIds: [...unreadIds], previousThread };
698
719
  },
699
- onError: (_err, _vars, context) => {
720
+ onError: (_err, threadId, context) => {
700
721
  for (const id of context?.overrideIds ?? []) {
701
722
  clearOptimisticOverride(id);
702
723
  }
703
724
  context?.previous.forEach(([key, data]) => qc.setQueryData(key, data));
725
+ if (context?.previousThread) {
726
+ setCachedThread(threadId, context.previousThread);
727
+ }
704
728
  },
705
729
  onSettled: () => delayedInvalidate(qc, [["emails"], ["labels"]]),
706
730
  });
@@ -74,6 +74,12 @@ function getHydrationStableLocaleInitScript() {
74
74
  const THEME_INIT_SCRIPT = getHydrationStableThemeInitScript();
75
75
  const LOCALE_INIT_SCRIPT = getHydrationStableLocaleInitScript();
76
76
 
77
+ function skipBroadActionInvalidation() {
78
+ // Mail's Gmail-backed reads are expensive and already refresh through the
79
+ // explicit app-state refresh-signal that mutating mail actions write.
80
+ return false;
81
+ }
82
+
77
83
  const MAIL_ERROR_COPY: Record<
78
84
  LocaleCode,
79
85
  { title: string; fallback: string; back: string; reload: string }
@@ -275,6 +281,7 @@ function DbSyncSetup() {
275
281
  useDbSync({
276
282
  queryClient: qc,
277
283
  queryKeys: [],
284
+ actionInvalidatePredicate: skipBroadActionInvalidation,
278
285
  // Skip events this tab caused — our mutations already handle cache updates
279
286
  ignoreSource: TAB_ID,
280
287
  onEvent: (data: {
@@ -328,8 +335,13 @@ function DbSyncSetup() {
328
335
  invalidateSettingsSurfaces();
329
336
  }
330
337
  } else if (data.source === "action") {
338
+ // The core sync hook already refreshes action-backed queries for action
339
+ // events. Email and label reads are refreshed by the explicit
340
+ // refresh-signal app-state event so generic action changes do not
341
+ // cancel and restart Gmail list requests.
342
+ } else if (data.source === "screen-refresh") {
331
343
  if (!isOwnEvent) {
332
- qc.invalidateQueries({ queryKey: ["action"] });
344
+ markExternalEmailRefresh();
333
345
  qc.invalidateQueries({ queryKey: ["emails"] });
334
346
  qc.invalidateQueries({ queryKey: ["email"] });
335
347
  qc.invalidateQueries({ queryKey: ["labels"] });
@@ -337,12 +349,6 @@ function DbSyncSetup() {
337
349
  }
338
350
  } else if (!isOwnEvent) {
339
351
  qc.invalidateQueries({ queryKey: ["action"] });
340
- qc.invalidateQueries({ queryKey: ["emails"] });
341
- qc.invalidateQueries({ queryKey: ["email"] });
342
- qc.invalidateQueries({ queryKey: ["labels"] });
343
- qc.invalidateQueries({ queryKey: ["settings"] });
344
- qc.invalidateQueries({ queryKey: ["aliases"] });
345
- invalidateSettingsSurfaces();
346
352
  }
347
353
  },
348
354
  });
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-06-26
4
+ ---
5
+
6
+ Mail avoids unnecessary message list reloads after background updates.
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
26
26
  * Body: { update: string (base64), requestSource?: string }
27
27
  */
28
28
  export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
29
- error: string;
30
29
  ok?: undefined;
30
+ error: string;
31
31
  } | {
32
32
  error?: undefined;
33
33
  ok: boolean;
@@ -42,8 +42,8 @@ export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import
42
42
  */
43
43
  export declare const postCollabText: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
44
44
  ok?: undefined;
45
- error: string;
46
45
  text?: undefined;
46
+ error: string;
47
47
  } | {
48
48
  error?: undefined;
49
49
  ok: boolean;
@@ -3,18 +3,18 @@ declare const _default: import("../../action.js").ActionDefinition<{
3
3
  url?: string;
4
4
  filename?: string;
5
5
  }, {
6
+ id?: undefined;
6
7
  error: string;
7
8
  configured?: undefined;
8
9
  connectPath?: undefined;
9
10
  url?: undefined;
10
- id?: undefined;
11
11
  provider?: undefined;
12
12
  } | {
13
+ id?: undefined;
13
14
  error: string;
14
15
  configured: boolean;
15
16
  connectPath: string;
16
17
  url?: undefined;
17
- id?: undefined;
18
18
  provider?: undefined;
19
19
  } | {
20
20
  error?: undefined;
@@ -28,7 +28,7 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
28
28
  } | {
29
29
  count?: undefined;
30
30
  updated?: undefined;
31
- error?: undefined;
32
31
  ok: boolean;
32
+ error?: undefined;
33
33
  }>>;
34
34
  //# sourceMappingURL=routes.d.ts.map
@@ -41,28 +41,28 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
41
41
  thumbsUpRate: number;
42
42
  avgEvalScore: number;
43
43
  } | {
44
- error?: undefined;
45
- ok?: undefined;
46
44
  summary: import("./types.js").TraceSummary;
47
45
  spans: import("./types.js").TraceSpan[];
48
46
  id?: undefined;
49
- } | {
50
47
  error?: undefined;
51
48
  ok?: undefined;
49
+ } | {
52
50
  summary?: undefined;
53
51
  spans?: undefined;
54
52
  id: string;
55
- } | {
53
+ error?: undefined;
56
54
  ok?: undefined;
55
+ } | {
57
56
  summary?: undefined;
58
57
  spans?: undefined;
59
- error: any;
60
58
  id?: undefined;
59
+ error: any;
60
+ ok?: undefined;
61
61
  } | {
62
- error?: undefined;
63
62
  summary?: undefined;
64
63
  spans?: undefined;
65
- ok: boolean;
66
64
  id?: undefined;
65
+ error?: undefined;
66
+ ok: boolean;
67
67
  }>>;
68
68
  //# sourceMappingURL=routes.d.ts.map
@@ -49,11 +49,11 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
49
49
  }>;
50
50
  /** DELETE /_agent-native/resources/:id — delete a resource */
51
51
  export declare function handleDeleteResource(event: any): Promise<{
52
- error: string;
53
52
  ok?: undefined;
53
+ error: string;
54
54
  } | {
55
- ok: boolean;
56
55
  error?: undefined;
56
+ ok: boolean;
57
57
  }>;
58
58
  /** POST /_agent-native/resources/upload — upload a file as a resource */
59
59
  export declare function handleUploadResource(event: any): Promise<import("./store.js").Resource | {
@@ -73,9 +73,9 @@ export declare function handleUploadResource(event: any): Promise<import("./stor
73
73
  runId: string | null;
74
74
  expiresAt: number | null;
75
75
  metadata: string | null;
76
+ error?: undefined;
76
77
  url: string;
77
78
  provider: string;
78
- error?: undefined;
79
79
  }>;
80
80
  export {};
81
81
  //# sourceMappingURL=handlers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"action-routes.d.ts","sourceRoot":"","sources":["../../src/server/action-routes.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAwBhE,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,eAAe,GAC5B,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAMrB;AA2HD,MAAM,WAAW,wBAAwB;IACvC,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7D,8DAA8D;IAC9D,oBAAoB,CAAC,EAAE,CACrB,KAAK,EAAE,GAAG,KACP,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtD,0DAA0D;IAC1D,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACvE;AAsBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,GAAG,EACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACpC,OAAO,CAAC,EAAE,wBAAwB,QA8MnC"}
1
+ {"version":3,"file":"action-routes.d.ts","sourceRoot":"","sources":["../../src/server/action-routes.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAwBhE,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,eAAe,GAC5B,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAMrB;AA2HD,MAAM,WAAW,wBAAwB;IACvC,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7D,8DAA8D;IAC9D,oBAAoB,CAAC,EAAE,CACrB,KAAK,EAAE,GAAG,KACP,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtD,0DAA0D;IAC1D,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACvE;AAsBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,GAAG,EACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACpC,OAAO,CAAC,EAAE,wBAAwB,QAkNnC"}
@@ -275,13 +275,17 @@ export function mountActionRoutes(nitroApp, actions, options) {
275
275
  // ignore
276
276
  }
277
277
  }
278
- // If the action returned a string, try to parse as JSON for a clean response
278
+ // If the action returned a string, try to parse as JSON for a
279
+ // clean response. Plain strings still need to go over the HTTP
280
+ // action transport as JSON, otherwise H3 sends text/plain and the
281
+ // browser action client rejects the successful 2xx response.
279
282
  if (typeof result === "string") {
280
283
  try {
281
284
  return JSON.parse(result);
282
285
  }
283
286
  catch {
284
- return result;
287
+ setResponseHeader(event, "Content-Type", "application/json");
288
+ return JSON.stringify(result);
285
289
  }
286
290
  }
287
291
  return result;
@@ -1 +1 @@
1
- {"version":3,"file":"action-routes.js","sourceRoot":"","sources":["../../src/server/action-routes.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n defineEventHandler,\n setResponseStatus,\n setResponseHeader,\n getMethod,\n getQuery,\n getHeader,\n} from \"h3\";\n\nimport { isAgentActionStopError } from \"../action.js\";\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport { readBody } from \"../server/h3-helpers.js\";\nimport { EMBED_TARGET_HEADER } from \"../shared/embed-auth.js\";\nimport {\n isMcpEmbedCorsOrigin,\n MCP_EMBED_CORS_ALLOW_HEADERS,\n shouldAllowMcpEmbedCredentials,\n} from \"../shared/mcp-embed-headers.js\";\nimport { notifyActionChange } from \"./action-change.js\";\nimport {\n getAllowedCorsOrigin as resolveAllowedCorsOrigin,\n readCorsAllowedOrigins,\n} from \"./cors-origins.js\";\n/**\n * Auto-mount actions as HTTP endpoints under /_agent-native/actions/:name.\n *\n * Actions are exposed as POST by default. Use `http: { method: \"GET\" }` in\n * defineAction to expose as GET. Use `http: false` to mark as agent-only.\n */\nimport { getH3App } from \"./framework-request-handler.js\";\nimport { runWithRequestContext } from \"./request-context.js\";\n\nconst ROUTE_PREFIX = \"/_agent-native/actions\";\n\nexport function parseActionSearchParams(\n searchParams: URLSearchParams,\n): Record<string, any> {\n const params: Record<string, any> = {};\n for (const [rawKey, value] of searchParams.entries()) {\n appendActionParam(params, rawKey, value);\n }\n return params;\n}\n\nfunction parseActionQueryObject(\n query: Record<string, unknown>,\n): Record<string, any> {\n const params: Record<string, any> = {};\n for (const [rawKey, rawValue] of Object.entries(query)) {\n const values = Array.isArray(rawValue) ? rawValue : [rawValue];\n for (const value of values) {\n if (value != null) appendActionParam(params, rawKey, String(value));\n }\n }\n return params;\n}\n\nfunction appendActionParam(\n params: Record<string, any>,\n rawKey: string,\n value: any,\n) {\n const isArrayKey = rawKey.endsWith(\"[]\");\n // The core client serializes arrays as `key[]=value` so even a single\n // value can validate against z.array() action schemas.\n const key = isArrayKey ? rawKey.slice(0, -2) : rawKey;\n const current = params[key];\n if (current === undefined) {\n params[key] = isArrayKey ? [value] : value;\n } else if (Array.isArray(current)) {\n current.push(value);\n } else {\n params[key] = [current, value];\n }\n}\n\n/**\n * Read the caller's IANA timezone from the `x-user-timezone` header. The core\n * client sends this on every action request so server-side \"today\" fallbacks\n * can honor the user's local day.\n */\nfunction readTimezoneHeader(event: any): string | undefined {\n try {\n const raw = getHeader(event, \"x-user-timezone\");\n if (!raw || typeof raw !== \"string\") return undefined;\n const trimmed = raw.trim();\n return trimmed.length > 0 && trimmed.length < 64 ? trimmed : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * True when the request originated from the browser action client\n * (`useActionQuery` / `useActionMutation` / `callAction`), which tags every\n * call with `X-Agent-Native-Frontend: 1`. Used to set `ctx.caller` to\n * `\"frontend\"` vs a bare programmatic `\"http\"` POST. The header carries no\n * auth weight — it only narrows the caller tag for tracking/branching.\n */\nfunction isFrontendActionRequest(event: any): boolean {\n try {\n return getHeader(event, \"x-agent-native-frontend\") === \"1\";\n } catch {\n return false;\n }\n}\n\ntype CorsOrigin = {\n origin: string;\n credentials: boolean;\n};\n\nfunction getAllowedCorsOrigin(origin: string | undefined): CorsOrigin | null {\n const allowedOrigin = resolveAllowedCorsOrigin(origin, {\n allowedOrigins: readCorsAllowedOrigins(),\n // Let the cors-origins default apply (dev-only). Omitting this option\n // keeps production from trusting arbitrary localhost callers.\n });\n if (allowedOrigin) {\n return { origin: allowedOrigin, credentials: true };\n }\n if (origin && isMcpEmbedCorsOrigin(origin)) {\n return {\n origin,\n credentials: shouldAllowMcpEmbedCredentials(origin),\n };\n }\n return null;\n}\n\nfunction handleOptionsRequest(event: any): string {\n const origin = getHeader(event, \"origin\");\n const cors = getAllowedCorsOrigin(\n typeof origin === \"string\" ? origin : undefined,\n );\n\n if (origin && !cors) {\n setResponseStatus(event, 403);\n return \"\";\n }\n\n if (cors) {\n setResponseHeader(event, \"Access-Control-Allow-Origin\", cors.origin);\n setResponseHeader(event, \"Vary\", \"Origin\");\n if (cors.credentials) {\n setResponseHeader(event, \"Access-Control-Allow-Credentials\", \"true\");\n }\n setResponseHeader(\n event,\n \"Access-Control-Allow-Methods\",\n \"GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS\",\n );\n setResponseHeader(\n event,\n \"Access-Control-Allow-Headers\",\n cors.credentials\n ? `Content-Type,Authorization,X-Requested-With,X-Request-Source,X-Agent-Native-CSRF,X-User-Timezone,X-Agent-Native-Tool-Bridge,X-Agent-Native-Tool-Id,X-Agent-Native-Frontend,${EMBED_TARGET_HEADER}`\n : `${MCP_EMBED_CORS_ALLOW_HEADERS},X-Agent-Native-Tool-Bridge,X-Agent-Native-Tool-Id,X-Agent-Native-Frontend`,\n );\n }\n\n setResponseStatus(event, 204);\n return \"\";\n}\n\nexport interface MountActionRoutesOptions {\n /** Resolve owner email from the H3 event (for data scoping). */\n getOwnerFromEvent?: (event: any) => string | Promise<string>;\n /** Resolve display name from the H3 event, when available. */\n getUserNameFromEvent?: (\n event: any,\n ) => string | undefined | Promise<string | undefined>;\n /** Resolve org ID from the H3 event (for org scoping). */\n resolveOrgId?: (event: any) => string | null | Promise<string | null>;\n}\n\nfunction isAuthResolutionFailure(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const maybeStatus = error as {\n status?: unknown;\n statusCode?: unknown;\n statusMessage?: unknown;\n };\n const status =\n typeof maybeStatus.statusCode === \"number\"\n ? maybeStatus.statusCode\n : typeof maybeStatus.status === \"number\"\n ? maybeStatus.status\n : undefined;\n if (status === 401 || status === 403) return true;\n return (\n typeof maybeStatus.statusMessage === \"string\" &&\n /unauthenticated|forbidden/i.test(maybeStatus.statusMessage)\n );\n}\n\n/**\n * Mount discovered actions as HTTP endpoints.\n *\n * Only actions from `autoDiscoverActions` (template actions) are mounted.\n * Built-in actions (resource-*, chat-*, shell, etc.) are NOT passed here.\n */\nexport function mountActionRoutes(\n nitroApp: any,\n actions: Record<string, ActionEntry>,\n options?: MountActionRoutesOptions,\n) {\n const mounted: string[] = [];\n\n for (const [name, entry] of Object.entries(actions)) {\n // Skip agent-only actions\n if (entry.http === false) continue;\n\n const method = entry.http?.method ?? \"POST\";\n const path = entry.http?.path ?? name;\n const routePath = `${ROUTE_PREFIX}/${path}`;\n\n getH3App(nitroApp).use(\n routePath,\n defineEventHandler(async (event) => {\n const reqMethod = getMethod(event);\n const effectiveMethod =\n reqMethod === \"HEAD\" && method === \"GET\" ? \"GET\" : reqMethod;\n\n if (reqMethod === \"OPTIONS\") {\n return handleOptionsRequest(event);\n }\n\n setResponseHeader(event, \"Cache-Control\", \"no-store\");\n\n // Allow the declared method\n if (effectiveMethod !== method) {\n setResponseStatus(event, 405);\n return { error: `Method not allowed. Use ${method}.` };\n }\n\n // (audit H5) Per-action `toolCallable` opt-out for the tools-iframe\n // bridge. The bridge tags every outbound action call with\n // X-Agent-Native-Tool-Bridge: 1. When that header is present and the\n // action declares `toolCallable: false`, we 403 — used by the\n // framework's share-resource / unshare-resource /\n // set-resource-visibility for defense-in-depth on auth-adjacent\n // operations. Undefined defaults to allow: tools are intra-org and\n // typically authored by trusted teammates, so the default is to\n // trust the org-level access controls.\n // The header is set by the parent (the React host), not by the\n // iframe's user-authored content; sanitizeToolRequestOptions strips\n // iframe attempts to spoof it.\n const fromToolBridge =\n getHeader(event, \"x-agent-native-tool-bridge\") === \"1\";\n if (fromToolBridge && entry.toolCallable === false) {\n setResponseStatus(event, 403);\n return {\n error: `Action '${name}' is not callable from tools.`,\n };\n }\n\n // Resolve auth context for per-request scoping\n let userEmail: string | undefined;\n let userName: string | undefined;\n if (options?.getOwnerFromEvent) {\n try {\n userEmail = await options.getOwnerFromEvent(event);\n userName = options?.getUserNameFromEvent\n ? await options.getUserNameFromEvent(event)\n : undefined;\n } catch (error) {\n if (\n entry.requiresAuth === false &&\n isAuthResolutionFailure(error)\n ) {\n userEmail = undefined;\n userName = undefined;\n } else {\n throw error;\n }\n }\n }\n const orgId = options?.resolveOrgId\n ? ((await options.resolveOrgId(event)) ?? undefined)\n : undefined;\n const timezone = readTimezoneHeader(event);\n\n return runWithRequestContext(\n { userEmail, userName, orgId, timezone },\n async () => {\n // Parse params based on method. On web-standard runtimes (Netlify\n // Functions, CF Workers), event.req IS the web Request — use .json()\n // directly. H3's readBody fails on those runtimes because it expects\n // a Node.js stream on event.node.req.\n let params: Record<string, any>;\n try {\n if (method === \"GET\") {\n // H3 v2: prefer web Request URL, fallback to getQuery\n const webReq = (event as any).req;\n if (webReq?.url) {\n const url = new URL(webReq.url);\n params = parseActionSearchParams(url.searchParams);\n } else {\n params = parseActionQueryObject(\n getQuery(event) as Record<string, any>,\n );\n }\n } else {\n const webReq = (event as any).req;\n if (webReq && typeof webReq.json === \"function\") {\n // H3 v2: event.req is the web Request — use .json() directly\n params = (await webReq.json().catch(() => null)) ?? {};\n } else {\n // Fallback: H3's readBody (Node.js dev)\n params = (await readBody(event)) ?? {};\n }\n }\n } catch {\n params = {};\n }\n\n // Run the action. Tag the caller: browser calls (useActionQuery /\n // useActionMutation / callAction) send X-Agent-Native-Frontend: 1,\n // so they become \"frontend\"; bare programmatic POSTs are \"http\".\n // userEmail / orgId mirror the request context resolved above (do\n // NOT inject a dev identity — leave undefined when unauthenticated).\n try {\n const caller = isFrontendActionRequest(event)\n ? \"frontend\"\n : \"http\";\n const result = await entry.run(params, {\n userEmail,\n orgId: orgId ?? null,\n caller,\n actionName: name,\n });\n\n // Auto-refresh the UI after a successful mutating action. GET\n // actions and actions explicitly flagged readOnly are skipped.\n // Other tabs' useDbSync will see source:\"action\" and invalidate\n // their action queries. The calling tab already refetches via\n // useActionMutation's onSuccess, so this is mainly cross-tab\n // sync (and parity with the agent's tool-call path).\n // Explicit entry.readOnly (true OR false) wins over the method\n // heuristic. defineAction already auto-infers GET → readOnly=true,\n // so for actions registered through that path entry.readOnly is\n // always set and the fallback just guards legacy wrap paths.\n const isReadOnly =\n typeof entry.readOnly === \"boolean\"\n ? entry.readOnly\n : method === \"GET\";\n if (!isReadOnly) {\n try {\n await notifyActionChange({\n actionName: name,\n ...(userEmail ? { owner: userEmail } : {}),\n });\n } catch {\n // ignore\n }\n }\n\n // If the action returned a string, try to parse as JSON for a clean response\n if (typeof result === \"string\") {\n try {\n return JSON.parse(result);\n } catch {\n return result;\n }\n }\n\n return result;\n } catch (err: any) {\n const msg = err?.message ?? String(err);\n const isValidationError = msg.startsWith(\n \"Invalid action parameters\",\n );\n const explicitStatus =\n typeof err?.statusCode === \"number\"\n ? err.statusCode\n : undefined;\n // Return 400 for validation errors, the explicit statusCode if\n // set, otherwise 500.\n const status = isValidationError ? 400 : (explicitStatus ?? 500);\n setResponseStatus(event, status);\n\n // Only echo the raw message for known-safe cases:\n // - validation errors (deterministic, parameter-shape only)\n // - explicit user-facing errors (AgentActionStopError / fail())\n // - errors with an explicit statusCode < 500 (client errors)\n // For uncategorized 500s, return a generic message and keep the\n // real detail server-side only — it can contain DB/driver/\n // upstream text we must not leak to HTTP callers.\n const isUserFacing =\n isValidationError ||\n isAgentActionStopError(err) ||\n (explicitStatus !== undefined && explicitStatus < 500);\n if (isUserFacing) {\n return { error: msg };\n }\n console.error(`[agent-native] action '${name}' failed:`, err);\n return { error: \"Internal server error\" };\n }\n },\n ); // end runWithRequestContext\n }),\n );\n\n mounted.push(`${method} ${routePath}`);\n }\n\n if (mounted.length > 0 && process.env.DEBUG)\n console.log(\n `[action-routes] Mounted ${mounted.length} action route(s): ${mounted.join(\", \")}`,\n );\n}\n"]}
1
+ {"version":3,"file":"action-routes.js","sourceRoot":"","sources":["../../src/server/action-routes.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n defineEventHandler,\n setResponseStatus,\n setResponseHeader,\n getMethod,\n getQuery,\n getHeader,\n} from \"h3\";\n\nimport { isAgentActionStopError } from \"../action.js\";\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport { readBody } from \"../server/h3-helpers.js\";\nimport { EMBED_TARGET_HEADER } from \"../shared/embed-auth.js\";\nimport {\n isMcpEmbedCorsOrigin,\n MCP_EMBED_CORS_ALLOW_HEADERS,\n shouldAllowMcpEmbedCredentials,\n} from \"../shared/mcp-embed-headers.js\";\nimport { notifyActionChange } from \"./action-change.js\";\nimport {\n getAllowedCorsOrigin as resolveAllowedCorsOrigin,\n readCorsAllowedOrigins,\n} from \"./cors-origins.js\";\n/**\n * Auto-mount actions as HTTP endpoints under /_agent-native/actions/:name.\n *\n * Actions are exposed as POST by default. Use `http: { method: \"GET\" }` in\n * defineAction to expose as GET. Use `http: false` to mark as agent-only.\n */\nimport { getH3App } from \"./framework-request-handler.js\";\nimport { runWithRequestContext } from \"./request-context.js\";\n\nconst ROUTE_PREFIX = \"/_agent-native/actions\";\n\nexport function parseActionSearchParams(\n searchParams: URLSearchParams,\n): Record<string, any> {\n const params: Record<string, any> = {};\n for (const [rawKey, value] of searchParams.entries()) {\n appendActionParam(params, rawKey, value);\n }\n return params;\n}\n\nfunction parseActionQueryObject(\n query: Record<string, unknown>,\n): Record<string, any> {\n const params: Record<string, any> = {};\n for (const [rawKey, rawValue] of Object.entries(query)) {\n const values = Array.isArray(rawValue) ? rawValue : [rawValue];\n for (const value of values) {\n if (value != null) appendActionParam(params, rawKey, String(value));\n }\n }\n return params;\n}\n\nfunction appendActionParam(\n params: Record<string, any>,\n rawKey: string,\n value: any,\n) {\n const isArrayKey = rawKey.endsWith(\"[]\");\n // The core client serializes arrays as `key[]=value` so even a single\n // value can validate against z.array() action schemas.\n const key = isArrayKey ? rawKey.slice(0, -2) : rawKey;\n const current = params[key];\n if (current === undefined) {\n params[key] = isArrayKey ? [value] : value;\n } else if (Array.isArray(current)) {\n current.push(value);\n } else {\n params[key] = [current, value];\n }\n}\n\n/**\n * Read the caller's IANA timezone from the `x-user-timezone` header. The core\n * client sends this on every action request so server-side \"today\" fallbacks\n * can honor the user's local day.\n */\nfunction readTimezoneHeader(event: any): string | undefined {\n try {\n const raw = getHeader(event, \"x-user-timezone\");\n if (!raw || typeof raw !== \"string\") return undefined;\n const trimmed = raw.trim();\n return trimmed.length > 0 && trimmed.length < 64 ? trimmed : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * True when the request originated from the browser action client\n * (`useActionQuery` / `useActionMutation` / `callAction`), which tags every\n * call with `X-Agent-Native-Frontend: 1`. Used to set `ctx.caller` to\n * `\"frontend\"` vs a bare programmatic `\"http\"` POST. The header carries no\n * auth weight — it only narrows the caller tag for tracking/branching.\n */\nfunction isFrontendActionRequest(event: any): boolean {\n try {\n return getHeader(event, \"x-agent-native-frontend\") === \"1\";\n } catch {\n return false;\n }\n}\n\ntype CorsOrigin = {\n origin: string;\n credentials: boolean;\n};\n\nfunction getAllowedCorsOrigin(origin: string | undefined): CorsOrigin | null {\n const allowedOrigin = resolveAllowedCorsOrigin(origin, {\n allowedOrigins: readCorsAllowedOrigins(),\n // Let the cors-origins default apply (dev-only). Omitting this option\n // keeps production from trusting arbitrary localhost callers.\n });\n if (allowedOrigin) {\n return { origin: allowedOrigin, credentials: true };\n }\n if (origin && isMcpEmbedCorsOrigin(origin)) {\n return {\n origin,\n credentials: shouldAllowMcpEmbedCredentials(origin),\n };\n }\n return null;\n}\n\nfunction handleOptionsRequest(event: any): string {\n const origin = getHeader(event, \"origin\");\n const cors = getAllowedCorsOrigin(\n typeof origin === \"string\" ? origin : undefined,\n );\n\n if (origin && !cors) {\n setResponseStatus(event, 403);\n return \"\";\n }\n\n if (cors) {\n setResponseHeader(event, \"Access-Control-Allow-Origin\", cors.origin);\n setResponseHeader(event, \"Vary\", \"Origin\");\n if (cors.credentials) {\n setResponseHeader(event, \"Access-Control-Allow-Credentials\", \"true\");\n }\n setResponseHeader(\n event,\n \"Access-Control-Allow-Methods\",\n \"GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS\",\n );\n setResponseHeader(\n event,\n \"Access-Control-Allow-Headers\",\n cors.credentials\n ? `Content-Type,Authorization,X-Requested-With,X-Request-Source,X-Agent-Native-CSRF,X-User-Timezone,X-Agent-Native-Tool-Bridge,X-Agent-Native-Tool-Id,X-Agent-Native-Frontend,${EMBED_TARGET_HEADER}`\n : `${MCP_EMBED_CORS_ALLOW_HEADERS},X-Agent-Native-Tool-Bridge,X-Agent-Native-Tool-Id,X-Agent-Native-Frontend`,\n );\n }\n\n setResponseStatus(event, 204);\n return \"\";\n}\n\nexport interface MountActionRoutesOptions {\n /** Resolve owner email from the H3 event (for data scoping). */\n getOwnerFromEvent?: (event: any) => string | Promise<string>;\n /** Resolve display name from the H3 event, when available. */\n getUserNameFromEvent?: (\n event: any,\n ) => string | undefined | Promise<string | undefined>;\n /** Resolve org ID from the H3 event (for org scoping). */\n resolveOrgId?: (event: any) => string | null | Promise<string | null>;\n}\n\nfunction isAuthResolutionFailure(error: unknown): boolean {\n if (!error || typeof error !== \"object\") return false;\n const maybeStatus = error as {\n status?: unknown;\n statusCode?: unknown;\n statusMessage?: unknown;\n };\n const status =\n typeof maybeStatus.statusCode === \"number\"\n ? maybeStatus.statusCode\n : typeof maybeStatus.status === \"number\"\n ? maybeStatus.status\n : undefined;\n if (status === 401 || status === 403) return true;\n return (\n typeof maybeStatus.statusMessage === \"string\" &&\n /unauthenticated|forbidden/i.test(maybeStatus.statusMessage)\n );\n}\n\n/**\n * Mount discovered actions as HTTP endpoints.\n *\n * Only actions from `autoDiscoverActions` (template actions) are mounted.\n * Built-in actions (resource-*, chat-*, shell, etc.) are NOT passed here.\n */\nexport function mountActionRoutes(\n nitroApp: any,\n actions: Record<string, ActionEntry>,\n options?: MountActionRoutesOptions,\n) {\n const mounted: string[] = [];\n\n for (const [name, entry] of Object.entries(actions)) {\n // Skip agent-only actions\n if (entry.http === false) continue;\n\n const method = entry.http?.method ?? \"POST\";\n const path = entry.http?.path ?? name;\n const routePath = `${ROUTE_PREFIX}/${path}`;\n\n getH3App(nitroApp).use(\n routePath,\n defineEventHandler(async (event) => {\n const reqMethod = getMethod(event);\n const effectiveMethod =\n reqMethod === \"HEAD\" && method === \"GET\" ? \"GET\" : reqMethod;\n\n if (reqMethod === \"OPTIONS\") {\n return handleOptionsRequest(event);\n }\n\n setResponseHeader(event, \"Cache-Control\", \"no-store\");\n\n // Allow the declared method\n if (effectiveMethod !== method) {\n setResponseStatus(event, 405);\n return { error: `Method not allowed. Use ${method}.` };\n }\n\n // (audit H5) Per-action `toolCallable` opt-out for the tools-iframe\n // bridge. The bridge tags every outbound action call with\n // X-Agent-Native-Tool-Bridge: 1. When that header is present and the\n // action declares `toolCallable: false`, we 403 — used by the\n // framework's share-resource / unshare-resource /\n // set-resource-visibility for defense-in-depth on auth-adjacent\n // operations. Undefined defaults to allow: tools are intra-org and\n // typically authored by trusted teammates, so the default is to\n // trust the org-level access controls.\n // The header is set by the parent (the React host), not by the\n // iframe's user-authored content; sanitizeToolRequestOptions strips\n // iframe attempts to spoof it.\n const fromToolBridge =\n getHeader(event, \"x-agent-native-tool-bridge\") === \"1\";\n if (fromToolBridge && entry.toolCallable === false) {\n setResponseStatus(event, 403);\n return {\n error: `Action '${name}' is not callable from tools.`,\n };\n }\n\n // Resolve auth context for per-request scoping\n let userEmail: string | undefined;\n let userName: string | undefined;\n if (options?.getOwnerFromEvent) {\n try {\n userEmail = await options.getOwnerFromEvent(event);\n userName = options?.getUserNameFromEvent\n ? await options.getUserNameFromEvent(event)\n : undefined;\n } catch (error) {\n if (\n entry.requiresAuth === false &&\n isAuthResolutionFailure(error)\n ) {\n userEmail = undefined;\n userName = undefined;\n } else {\n throw error;\n }\n }\n }\n const orgId = options?.resolveOrgId\n ? ((await options.resolveOrgId(event)) ?? undefined)\n : undefined;\n const timezone = readTimezoneHeader(event);\n\n return runWithRequestContext(\n { userEmail, userName, orgId, timezone },\n async () => {\n // Parse params based on method. On web-standard runtimes (Netlify\n // Functions, CF Workers), event.req IS the web Request — use .json()\n // directly. H3's readBody fails on those runtimes because it expects\n // a Node.js stream on event.node.req.\n let params: Record<string, any>;\n try {\n if (method === \"GET\") {\n // H3 v2: prefer web Request URL, fallback to getQuery\n const webReq = (event as any).req;\n if (webReq?.url) {\n const url = new URL(webReq.url);\n params = parseActionSearchParams(url.searchParams);\n } else {\n params = parseActionQueryObject(\n getQuery(event) as Record<string, any>,\n );\n }\n } else {\n const webReq = (event as any).req;\n if (webReq && typeof webReq.json === \"function\") {\n // H3 v2: event.req is the web Request — use .json() directly\n params = (await webReq.json().catch(() => null)) ?? {};\n } else {\n // Fallback: H3's readBody (Node.js dev)\n params = (await readBody(event)) ?? {};\n }\n }\n } catch {\n params = {};\n }\n\n // Run the action. Tag the caller: browser calls (useActionQuery /\n // useActionMutation / callAction) send X-Agent-Native-Frontend: 1,\n // so they become \"frontend\"; bare programmatic POSTs are \"http\".\n // userEmail / orgId mirror the request context resolved above (do\n // NOT inject a dev identity — leave undefined when unauthenticated).\n try {\n const caller = isFrontendActionRequest(event)\n ? \"frontend\"\n : \"http\";\n const result = await entry.run(params, {\n userEmail,\n orgId: orgId ?? null,\n caller,\n actionName: name,\n });\n\n // Auto-refresh the UI after a successful mutating action. GET\n // actions and actions explicitly flagged readOnly are skipped.\n // Other tabs' useDbSync will see source:\"action\" and invalidate\n // their action queries. The calling tab already refetches via\n // useActionMutation's onSuccess, so this is mainly cross-tab\n // sync (and parity with the agent's tool-call path).\n // Explicit entry.readOnly (true OR false) wins over the method\n // heuristic. defineAction already auto-infers GET → readOnly=true,\n // so for actions registered through that path entry.readOnly is\n // always set and the fallback just guards legacy wrap paths.\n const isReadOnly =\n typeof entry.readOnly === \"boolean\"\n ? entry.readOnly\n : method === \"GET\";\n if (!isReadOnly) {\n try {\n await notifyActionChange({\n actionName: name,\n ...(userEmail ? { owner: userEmail } : {}),\n });\n } catch {\n // ignore\n }\n }\n\n // If the action returned a string, try to parse as JSON for a\n // clean response. Plain strings still need to go over the HTTP\n // action transport as JSON, otherwise H3 sends text/plain and the\n // browser action client rejects the successful 2xx response.\n if (typeof result === \"string\") {\n try {\n return JSON.parse(result);\n } catch {\n setResponseHeader(event, \"Content-Type\", \"application/json\");\n return JSON.stringify(result);\n }\n }\n\n return result;\n } catch (err: any) {\n const msg = err?.message ?? String(err);\n const isValidationError = msg.startsWith(\n \"Invalid action parameters\",\n );\n const explicitStatus =\n typeof err?.statusCode === \"number\"\n ? err.statusCode\n : undefined;\n // Return 400 for validation errors, the explicit statusCode if\n // set, otherwise 500.\n const status = isValidationError ? 400 : (explicitStatus ?? 500);\n setResponseStatus(event, status);\n\n // Only echo the raw message for known-safe cases:\n // - validation errors (deterministic, parameter-shape only)\n // - explicit user-facing errors (AgentActionStopError / fail())\n // - errors with an explicit statusCode < 500 (client errors)\n // For uncategorized 500s, return a generic message and keep the\n // real detail server-side only — it can contain DB/driver/\n // upstream text we must not leak to HTTP callers.\n const isUserFacing =\n isValidationError ||\n isAgentActionStopError(err) ||\n (explicitStatus !== undefined && explicitStatus < 500);\n if (isUserFacing) {\n return { error: msg };\n }\n console.error(`[agent-native] action '${name}' failed:`, err);\n return { error: \"Internal server error\" };\n }\n },\n ); // end runWithRequestContext\n }),\n );\n\n mounted.push(`${method} ${routePath}`);\n }\n\n if (mounted.length > 0 && process.env.DEBUG)\n console.log(\n `[action-routes] Mounted ${mounted.length} action route(s): ${mounted.join(\", \")}`,\n );\n}\n"]}
@@ -23,15 +23,15 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
23
23
  error: string;
24
24
  }>;
25
25
  export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
26
- ok?: undefined;
27
26
  error: any;
28
27
  key?: undefined;
29
28
  scope?: undefined;
29
+ ok?: undefined;
30
30
  } | {
31
- error?: undefined;
32
31
  ok: boolean;
33
32
  key: string;
34
33
  scope: AgentEngineApiKeyScope;
34
+ error?: undefined;
35
35
  }>>;
36
36
  export {};
37
37
  //# sourceMappingURL=agent-engine-api-key-route.d.ts.map
@@ -20,7 +20,7 @@ export declare function createTranscribeVoiceHandler(): import("h3").EventHandle
20
20
  error: string;
21
21
  text?: undefined;
22
22
  } | {
23
- text: string;
24
23
  error?: undefined;
24
+ text: string;
25
25
  }>>;
26
26
  //# sourceMappingURL=transcribe-voice.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.79.9",
3
+ "version": "0.79.10",
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": {