@agent-native/core 0.141.5 → 0.141.6

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 (43) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +13 -6
  3. package/corpus/templates/analytics/actions/get-first-party-analytics-health.ts +15 -1
  4. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +2 -2
  5. package/corpus/templates/analytics/app/i18n-data.ts +328 -0
  6. package/corpus/templates/analytics/app/pages/DataSources.tsx +66 -30
  7. package/corpus/templates/analytics/changelog/2026-08-05-historical-analytics-rollups-now-repair-automatically-after-.md +6 -0
  8. package/corpus/templates/analytics/netlify.toml +4 -0
  9. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +109 -0
  10. package/corpus/templates/analytics/server/jobs/analytics-rollup-backfill.ts +342 -0
  11. package/corpus/templates/analytics/server/lib/analytics-rollup-lock.ts +8 -0
  12. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +11 -29
  13. package/corpus/templates/analytics/server/lib/dashboards-store.ts +55 -0
  14. package/corpus/templates/analytics/server/lib/first-party-analytics-health.ts +117 -31
  15. package/corpus/templates/analytics/server/lib/first-party-analytics-rollups.ts +15 -9
  16. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +5 -16
  17. package/corpus/templates/analytics/server/plugins/analytics-rollup-backfill-jobs.ts +61 -0
  18. package/corpus/templates/analytics/server/plugins/db.ts +58 -187
  19. package/corpus/templates/analytics/server/routes/api/analytics-rollups/backfill.post.ts +53 -0
  20. package/corpus/templates/clips/changelog/2026-08-05-clips-overlays-now-use-clean-surfaces-without-clipped-shadow.md +6 -0
  21. package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +2 -2
  22. package/corpus/templates/clips/desktop/src/styles.css +3 -54
  23. package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +3 -3
  24. package/corpus/templates/design/actions/get-design-system.ts +3 -1
  25. package/corpus/templates/design/changelog/2026-08-05-missing-design-systems-now-return-a-clear-not-found-response.md +6 -0
  26. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +2 -2
  27. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +1 -1
  28. package/corpus/templates/slides/app/i18n/en-US.ts +5 -5
  29. package/corpus/templates/slides/changelog/2026-08-05-new-presentation-prompts-now-clearly-describe-presentation-g.md +6 -0
  30. package/dist/client/AssistantChat.js +1 -1
  31. package/dist/client/chat/run-recovery.d.ts +2 -1
  32. package/dist/client/chat/run-recovery.js +10 -3
  33. package/dist/client/error-format.d.ts +1 -0
  34. package/dist/client/error-format.js +4 -2
  35. package/dist/collab/struct-routes.d.ts +1 -1
  36. package/dist/observability/routes.d.ts +3 -3
  37. package/dist/progress/routes.d.ts +1 -1
  38. package/dist/resources/handlers.d.ts +1 -1
  39. package/dist/secrets/routes.d.ts +3 -3
  40. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  41. package/package.json +1 -1
  42. package/corpus/templates/analytics/changelog/2026-08-05-historical-analytics-rollups-stay-complete-and-atomic.md +0 -6
  43. package/corpus/templates/analytics/changelog/2026-08-05-historical-rollups-stay-complete-while-live-events-arrive.md +0 -6
@@ -8,6 +8,7 @@ import { useState, useEffect, useCallback, useRef } from "react";
8
8
  import { saveAgentEngineApiKey, } from "../agent-engine-key.js";
9
9
  import { agentNativePath } from "../api-path.js";
10
10
  import { writeClipboardText } from "../clipboard.js";
11
+ import { isProviderAuthenticationError } from "../error-format.js";
11
12
  import { useT } from "../i18n.js";
12
13
  import { useBuilderConnectFlow } from "../settings/useBuilderStatus.js";
13
14
  import { cn } from "../utils.js";
@@ -215,7 +216,7 @@ export function BuilderSetupCard({ onConnected, bouncePulse, fullWidth, layout =
215
216
  : "mx-auto w-full max-w-[42rem] px-3 pb-2 sm:w-fit"), children: _jsx("div", { className: cn("agent-builder-setup-card__panel rounded-lg border border-border/80 bg-background/80 shadow-sm backdrop-blur", sidebarLayout ? "p-2.5" : "p-3"), children: _jsx(BuilderSetupContent, { onConnected: onConnected, layout: layout }) }) }));
216
217
  }
217
218
  // ─── RunErrorRecoveryCard ─────────────────────────────────────────────────────
218
- export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDismiss, }) {
219
+ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDismiss, onProviderConnected, }) {
219
220
  const [detailsOpen, setDetailsOpen] = useState(false);
220
221
  const [copyState, setCopyState] = useState("idle");
221
222
  const [forking, setForking] = useState(false);
@@ -225,6 +226,8 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
225
226
  });
226
227
  const canRecover = info.recoverable === true;
227
228
  const shouldShowBuilderReconnect = isBuilderReconnectRunError(info);
229
+ const isProviderAuthError = isProviderAuthenticationError([info.message, info.details].filter(Boolean).join("\n"), info.errorCode);
230
+ const canRetry = canRecover || isProviderAuthError;
228
231
  const builderReconnectResolved = shouldShowBuilderReconnect &&
229
232
  builderReconnect.hasFetchedStatus &&
230
233
  builderReconnect.configured;
@@ -254,6 +257,10 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
254
257
  window.dispatchEvent(new CustomEvent("agent-chat:new-chat"));
255
258
  onDismiss();
256
259
  }, [onDismiss]);
260
+ const handleProviderConnected = useCallback(() => {
261
+ onProviderConnected?.();
262
+ onDismiss();
263
+ }, [onDismiss, onProviderConnected]);
257
264
  const handleFork = useCallback(async () => {
258
265
  if (!onFork || forking)
259
266
  return;
@@ -277,9 +284,9 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
277
284
  onDismiss();
278
285
  }
279
286
  }, [builderReconnectResolved, onDismiss]);
280
- return (_jsxs("div", { className: "rounded-lg border border-amber-500/25 bg-amber-500/[0.06] p-3 text-sm", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-500/10 text-amber-700 dark:text-amber-300", children: _jsx(IconAlertTriangle, { size: 14 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-foreground", children: runErrorHeadline(info) }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: info.message }), shouldShowBuilderReconnect && !builderReconnectResolved && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: "The current Builder.io or model-provider credential was rejected. Reconnect Builder.io (free tier available), then retry this message." })), isConnectionRecoveryError && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: "If retry lands on the same error, start a new chat session and continue from what already changed." })), (info.runId || info.errorCode || info.details) && (_jsxs("button", { type: "button", onClick: () => setDetailsOpen((v) => !v), className: "mt-2 inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { size: 12, className: cn("transition-transform", detailsOpen && "rotate-180") }), "Details"] })), detailsOpen && (_jsxs("div", { className: "mt-2 rounded-md border border-border/60 bg-background/70 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: [info.runId && _jsxs("div", { children: ["run: ", info.runId] }), info.errorCode && _jsxs("div", { children: ["code: ", info.errorCode] }), info.details && (_jsx("pre", { className: "mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono", children: info.details }))] }))] }), _jsx("button", { type: "button", onClick: onDismiss, "aria-label": "Dismiss", className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-background/80 hover:text-foreground", children: _jsx(IconX, { size: 14 }) })] }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [shouldShowBuilderReconnect && !builderReconnectResolved && (_jsxs("button", { type: "button", onClick: () => builderReconnect.start(), disabled: builderReconnect.connecting, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90 disabled:cursor-wait disabled:opacity-70", children: [builderReconnect.connecting ? (_jsx(IconLoader2, { size: 13, className: "animate-spin" })) : null, builderReconnect.connecting
287
+ return (_jsxs("div", { className: "rounded-lg border border-amber-500/25 bg-amber-500/[0.06] p-3 text-sm", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-500/10 text-amber-700 dark:text-amber-300", children: _jsx(IconAlertTriangle, { size: 14 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-foreground", children: runErrorHeadline(info) }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: info.message }), isProviderAuthError && (_jsx("div", { className: "mt-3 rounded-md border border-border/70 bg-background/60 p-2.5", children: _jsx(BuilderSetupContent, { layout: "sidebar", onConnected: handleProviderConnected }) })), shouldShowBuilderReconnect && !builderReconnectResolved && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: "The current Builder.io or model-provider credential was rejected. Reconnect Builder.io (free tier available), then retry this message." })), isConnectionRecoveryError && (_jsx("p", { className: "mt-2 text-xs leading-relaxed text-muted-foreground", children: "If retry lands on the same error, start a new chat session and continue from what already changed." })), (info.runId || info.errorCode || info.details) && (_jsxs("button", { type: "button", onClick: () => setDetailsOpen((v) => !v), className: "mt-2 inline-flex items-center gap-1 text-[11px] font-medium text-muted-foreground hover:text-foreground", children: [_jsx(IconChevronDown, { size: 12, className: cn("transition-transform", detailsOpen && "rotate-180") }), "Details"] })), detailsOpen && (_jsxs("div", { className: "mt-2 rounded-md border border-border/60 bg-background/70 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground", children: [info.runId && _jsxs("div", { children: ["run: ", info.runId] }), info.errorCode && _jsxs("div", { children: ["code: ", info.errorCode] }), info.details && (_jsx("pre", { className: "mt-2 max-h-28 overflow-auto whitespace-pre-wrap break-words font-mono", children: info.details }))] }))] }), _jsx("button", { type: "button", onClick: onDismiss, "aria-label": "Dismiss", className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-background/80 hover:text-foreground", children: _jsx(IconX, { size: 14 }) })] }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [shouldShowBuilderReconnect && !builderReconnectResolved && (_jsxs("button", { type: "button", onClick: () => builderReconnect.start(), disabled: builderReconnect.connecting, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90 disabled:cursor-wait disabled:opacity-70", children: [builderReconnect.connecting ? (_jsx(IconLoader2, { size: 13, className: "animate-spin" })) : null, builderReconnect.connecting
281
288
  ? "Connecting Builder.io"
282
- : "Reconnect Builder.io"] })), canRecover && (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", onClick: onContinue, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90", children: [_jsx(IconPlayerPlay, { size: 13 }), "Continue"] }), _jsxs("button", { type: "button", onClick: onRetry, className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconRefresh, { size: 13 }), isQueryError ? "Diagnose and retry" : "Retry"] })] })), canRecover && isConnectionRecoveryError && (_jsxs("button", { type: "button", onClick: startNewChat, className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconPlus, { size: 13 }), "New chat"] })), canRecover && onFork && !isConnectionRecoveryError && (_jsxs("button", { type: "button", onClick: handleFork, disabled: forking, title: "Fork this conversation into a separate chat thread.", "aria-label": "Fork this conversation into a separate chat thread", className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent disabled:cursor-wait disabled:opacity-70", children: [forking ? (_jsx(IconLoader2, { size: 13, className: "animate-spin" })) : (_jsx(IconGitFork, { size: 13 })), forking ? "Forking..." : "Fork chat"] })), _jsxs("button", { type: "button", onClick: copyDetails, className: "ml-auto inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs font-medium text-muted-foreground hover:bg-background/80 hover:text-foreground", children: [copyState === "copied" ? (_jsx(IconCheck, { size: 13 })) : copyState === "failed" ? (_jsx(IconX, { size: 13 })) : (_jsx(IconCopy, { size: 13 })), _jsx("span", { "aria-live": "polite", children: copyState === "copied"
289
+ : "Reconnect Builder.io"] })), canRecover && (_jsx(_Fragment, { children: _jsxs("button", { type: "button", onClick: onContinue, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90", children: [_jsx(IconPlayerPlay, { size: 13 }), "Continue"] }) })), canRetry && (_jsxs("button", { type: "button", onClick: onRetry, className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconRefresh, { size: 13 }), isQueryError ? "Diagnose and retry" : "Retry"] })), canRecover && isConnectionRecoveryError && (_jsxs("button", { type: "button", onClick: startNewChat, className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent", children: [_jsx(IconPlus, { size: 13 }), "New chat"] })), canRecover && onFork && !isConnectionRecoveryError && (_jsxs("button", { type: "button", onClick: handleFork, disabled: forking, title: "Fork this conversation into a separate chat thread.", "aria-label": "Fork this conversation into a separate chat thread", className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background px-3 text-xs font-medium text-foreground hover:bg-accent disabled:cursor-wait disabled:opacity-70", children: [forking ? (_jsx(IconLoader2, { size: 13, className: "animate-spin" })) : (_jsx(IconGitFork, { size: 13 })), forking ? "Forking..." : "Fork chat"] })), _jsxs("button", { type: "button", onClick: copyDetails, className: "ml-auto inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs font-medium text-muted-foreground hover:bg-background/80 hover:text-foreground", children: [copyState === "copied" ? (_jsx(IconCheck, { size: 13 })) : copyState === "failed" ? (_jsx(IconX, { size: 13 })) : (_jsx(IconCopy, { size: 13 })), _jsx("span", { "aria-live": "polite", children: copyState === "copied"
283
290
  ? "Copied"
284
291
  : copyState === "failed"
285
292
  ? "Copy failed"
@@ -18,4 +18,5 @@ export interface NormalizedChatError {
18
18
  message: string;
19
19
  details?: string;
20
20
  }
21
+ export declare function isProviderAuthenticationError(text: string, errorCode?: string): boolean;
21
22
  export declare function normalizeChatError(errorMessage: string, errorCode?: string): NormalizedChatError;
@@ -60,7 +60,7 @@ function isProviderRateLimit(text, errorCode) {
60
60
  /\b(?:http\s*)?429\b.*\b(?:status|too many requests|rate[-_\s]?limit|no body)\b/i.test(text) ||
61
61
  /\b(?:too many requests|rate[-_\s]?limit(?:ed| exceeded)?)\b/i.test(text));
62
62
  }
63
- function isProviderAuthenticationError(text, errorCode) {
63
+ export function isProviderAuthenticationError(text, errorCode) {
64
64
  const code = normalizeErrorCode(errorCode);
65
65
  const lower = text.toLowerCase();
66
66
  return (code === "authentication_error" ||
@@ -72,6 +72,8 @@ function isProviderAuthenticationError(text, errorCode) {
72
72
  lower.includes("invalid api key") ||
73
73
  lower.includes("incorrect api key") ||
74
74
  lower.includes("api key is invalid") ||
75
+ lower.includes("rejected the saved api key") ||
76
+ lower.includes("saved provider key was rejected") ||
75
77
  (lower.includes("authentication_error") && lower.includes("api")));
76
78
  }
77
79
  function isConnectionError(text, errorCode) {
@@ -115,7 +117,7 @@ export function normalizeChatError(errorMessage, errorCode) {
115
117
  }
116
118
  if (isProviderAuthenticationError(text, errorCode)) {
117
119
  return {
118
- message: "The model provider rejected the saved API key. Update the key in Settings → Integrations → API keys, then retry.",
120
+ message: "The saved provider key was rejected. Connect Builder.io for managed AI, or update your provider key, then retry.",
119
121
  details: text,
120
122
  };
121
123
  }
@@ -13,8 +13,8 @@
13
13
  * Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
14
14
  */
15
15
  export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
16
- error: string;
17
16
  ok?: undefined;
17
+ error: string;
18
18
  } | {
19
19
  error?: undefined;
20
20
  ok: boolean;
@@ -42,22 +42,22 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
42
42
  avgEvalScore: number;
43
43
  } | {
44
44
  error?: undefined;
45
+ ok?: undefined;
45
46
  summary: import("./types.js").TraceSummary;
46
47
  spans: import("./types.js").TraceSpan[];
47
48
  id?: undefined;
48
- ok?: undefined;
49
49
  } | {
50
50
  error?: undefined;
51
+ ok?: undefined;
51
52
  summary?: undefined;
52
53
  spans?: undefined;
53
54
  id: string;
54
- ok?: undefined;
55
55
  } | {
56
+ ok?: undefined;
56
57
  summary?: undefined;
57
58
  spans?: undefined;
58
59
  id?: undefined;
59
60
  error: any;
60
- ok?: undefined;
61
61
  } | {
62
62
  error?: undefined;
63
63
  summary?: undefined;
@@ -15,6 +15,6 @@ export declare function createProgressHandler(): import("h3").EventHandlerWithFe
15
15
  error: string;
16
16
  ok?: undefined;
17
17
  } | {
18
- ok: boolean;
19
18
  error?: undefined;
19
+ ok: boolean;
20
20
  }>>;
@@ -48,8 +48,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
48
48
  }>;
49
49
  /** DELETE /_agent-native/resources/:id — delete a resource */
50
50
  export declare function handleDeleteResource(event: any): Promise<{
51
- error: string;
52
51
  ok?: undefined;
52
+ error: string;
53
53
  } | {
54
54
  error?: undefined;
55
55
  ok: boolean;
@@ -34,16 +34,16 @@ export declare function createListSecretsHandler(): import("h3").EventHandlerWit
34
34
  /** POST /_agent-native/secrets/:key — write a secret. */
35
35
  export declare function createWriteSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
36
36
  error: string;
37
- status?: undefined;
38
37
  ok?: undefined;
38
+ status?: undefined;
39
39
  } | {
40
40
  ok: boolean;
41
41
  status: string;
42
42
  error?: undefined;
43
43
  } | {
44
+ ok?: undefined;
44
45
  error: string;
45
46
  removed?: undefined;
46
- ok?: undefined;
47
47
  } | {
48
48
  ok: boolean;
49
49
  removed: boolean;
@@ -54,9 +54,9 @@ export declare function createWriteSecretHandler(): import("h3").EventHandlerWit
54
54
  * or the current stored value without changing anything.
55
55
  */
56
56
  export declare function createTestSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
57
+ ok?: undefined;
57
58
  error: string;
58
59
  note?: undefined;
59
- ok?: undefined;
60
60
  } | {
61
61
  ok: boolean;
62
62
  note?: undefined;
@@ -27,10 +27,10 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
27
27
  export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
28
28
  error: any;
29
29
  } | {
30
- error?: undefined;
31
30
  ok: boolean;
32
31
  key: string;
33
32
  baseUrlKey?: string;
34
33
  scope: AgentEngineApiKeyScope;
34
+ error?: undefined;
35
35
  }>>;
36
36
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.141.5",
3
+ "version": "0.141.6",
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": {
@@ -1,6 +0,0 @@
1
- ---
2
- type: fixed
3
- date: 2026-08-05
4
- ---
5
-
6
- Historical analytics events now populate rollups, and new events update raw data and rollups atomically.
@@ -1,6 +0,0 @@
1
- ---
2
- type: fixed
3
- date: 2026-08-05
4
- ---
5
-
6
- Historical analytics rollups stay complete while live events arrive.