@agent-native/core 0.168.6 → 0.168.9

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 (87) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/actions/mutate-dashboard.ts +8 -1
  3. package/corpus/templates/calendar/actions/delete-event.ts +34 -18
  4. package/corpus/templates/calendar/actions/delete-events.ts +13 -1
  5. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +22 -3
  6. package/corpus/templates/calendar/app/lib/calendar-timezone.ts +19 -0
  7. package/corpus/templates/calendar/server/lib/google-api.ts +18 -1
  8. package/corpus/templates/clips/actions/finalize-meeting.ts +16 -0
  9. package/corpus/templates/clips/actions/list-meetings.ts +1 -0
  10. package/corpus/templates/clips/actions/list-recordings.ts +14 -0
  11. package/corpus/templates/clips/actions/sync-calendars.ts +10 -29
  12. package/corpus/templates/clips/app/components/library/recording-card.tsx +2 -2
  13. package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +20 -3
  14. package/corpus/templates/clips/app/hooks/use-library.ts +1 -0
  15. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +12 -5
  16. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +28 -12
  17. package/corpus/templates/clips/desktop/src/lib/meeting-stop.ts +16 -0
  18. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +19 -9
  19. package/corpus/templates/factory/.agents/skills/factory-graphs/SKILL.md +5 -0
  20. package/corpus/templates/factory/AGENTS.md +12 -22
  21. package/corpus/templates/factory/README.md +11 -8
  22. package/corpus/templates/factory/actions/approve-factory-item.ts +35 -8
  23. package/corpus/templates/factory/actions/babysit-agent-native-pull-request.ts +24 -9
  24. package/corpus/templates/factory/actions/create-factory.ts +211 -0
  25. package/corpus/templates/factory/actions/evaluate-triage-item.ts +29 -5
  26. package/corpus/templates/factory/actions/get-factory-graph.ts +1 -1
  27. package/corpus/templates/factory/actions/get-slack-feedback-context.ts +20 -11
  28. package/corpus/templates/factory/actions/get-triage-config.ts +13 -12
  29. package/corpus/templates/factory/actions/get-triage-item.ts +28 -6
  30. package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +33 -17
  31. package/corpus/templates/factory/actions/ingest-github-observation.ts +10 -4
  32. package/corpus/templates/factory/actions/list-factory-audit.ts +11 -4
  33. package/corpus/templates/factory/actions/list-factory-automations.ts +34 -12
  34. package/corpus/templates/factory/actions/list-triage-items.ts +11 -3
  35. package/corpus/templates/factory/actions/list-triage-rules.ts +11 -4
  36. package/corpus/templates/factory/actions/poll-github-sources.ts +24 -10
  37. package/corpus/templates/factory/actions/poll-sentry-errors.ts +26 -11
  38. package/corpus/templates/factory/actions/poll-slack-channel.ts +31 -13
  39. package/corpus/templates/factory/actions/reconcile-triage-run.ts +59 -9
  40. package/corpus/templates/factory/actions/record-triage-feedback.ts +14 -3
  41. package/corpus/templates/factory/actions/run-factory-automation.ts +12 -2
  42. package/corpus/templates/factory/actions/save-factory-automation.ts +82 -21
  43. package/corpus/templates/factory/actions/save-factory-graph.ts +10 -1
  44. package/corpus/templates/factory/actions/save-triage-config.ts +90 -36
  45. package/corpus/templates/factory/actions/save-triage-rule.ts +16 -3
  46. package/corpus/templates/factory/actions/start-builder-for-item.ts +28 -20
  47. package/corpus/templates/factory/actions/suggest-factory-rules.ts +11 -4
  48. package/corpus/templates/factory/actions/view-screen.ts +22 -30
  49. package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +7 -2
  50. package/corpus/templates/factory/app/components/factory/FactoryWorkspaceActions.tsx +7 -22
  51. package/corpus/templates/factory/app/components/factory/NewFactoryForm.tsx +260 -0
  52. package/corpus/templates/factory/app/components/layout/Layout.tsx +1 -1
  53. package/corpus/templates/factory/app/components/layout/Sidebar.tsx +2 -1
  54. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +3 -3
  55. package/corpus/templates/factory/app/i18n/en-US.ts +18 -1
  56. package/corpus/templates/factory/app/routes/factory.tsx +78 -62
  57. package/corpus/templates/factory/app/routes/{factory-settings.tsx → new-factory.tsx} +12 -9
  58. package/corpus/templates/factory/server/db/schema.ts +18 -3
  59. package/corpus/templates/factory/server/factory-graph/contracts.ts +24 -0
  60. package/corpus/templates/factory/server/factory-graph/store.ts +16 -9
  61. package/corpus/templates/factory/server/lib/factory-automation-plan.ts +136 -0
  62. package/corpus/templates/factory/server/lib/factory-automation-repair.ts +31 -0
  63. package/corpus/templates/factory/server/lib/factory-scope.ts +416 -0
  64. package/corpus/templates/factory/server/lib/require-factory-automation.ts +11 -0
  65. package/corpus/templates/factory/server/plugins/agent-chat.ts +4 -2
  66. package/corpus/templates/factory/server/plugins/factory-migrations.ts +80 -0
  67. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +142 -43
  68. package/corpus/templates/factory/server/triage/audit.ts +4 -0
  69. package/corpus/templates/factory/server/triage/ids.ts +4 -0
  70. package/dist/cli/native-dependencies.js +4 -1
  71. package/dist/client/AgentPanel.d.ts +5 -1
  72. package/dist/client/AgentPanel.js +9 -4
  73. package/dist/client/agent-chat/index.d.ts +1 -1
  74. package/dist/client/agent-chat/index.js +1 -1
  75. package/dist/client/chat-first/apps-rail.js +6 -6
  76. package/dist/client/chat-first/primary-nav.js +14 -6
  77. package/dist/client/integrations/IntegrationsPanel.d.ts +15 -0
  78. package/dist/client/integrations/IntegrationsPanel.js +29 -21
  79. package/dist/client/integrations/index.d.ts +1 -1
  80. package/dist/client/integrations/index.js +1 -1
  81. package/dist/client/resources/McpIntegrationDialog.js +1 -1
  82. package/dist/collab/routes.d.ts +1 -1
  83. package/dist/notifications/routes.d.ts +1 -1
  84. package/dist/progress/routes.d.ts +1 -1
  85. package/dist/resources/handlers.d.ts +3 -3
  86. package/dist/server/ssr-handler.js +19 -1
  87. package/package.json +1 -1
@@ -1,3 +1,18 @@
1
1
  import React from "react";
2
2
  export declare function LegacyIntegrationsPanel(): React.JSX.Element;
3
+ export interface McpIntegrationsSectionProps {
4
+ query?: string;
5
+ title?: string;
6
+ description?: string;
7
+ showTitle?: boolean;
8
+ showDescription?: boolean;
9
+ showHeader?: boolean;
10
+ className?: string;
11
+ onOAuthStart?: (url: string) => void | Promise<void>;
12
+ oauthReturnPath?: string;
13
+ }
14
+ export declare function McpIntegrationsSection({ query, title, description, showTitle, showDescription, showHeader, className, onOAuthStart, oauthReturnPath, }: McpIntegrationsSectionProps): React.JSX.Element;
15
+ export interface McpIntegrationsLandingProps extends Omit<McpIntegrationsSectionProps, "query" | "showHeader"> {
16
+ }
17
+ export declare function McpIntegrationsLanding({ title, description, ...props }: McpIntegrationsLandingProps): React.JSX.Element;
3
18
  export declare function IntegrationsPanel(): React.JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { IconPlus, IconBrandSlack, IconBrandTelegram, IconBrandWhatsapp, IconBrandGoogleDrive, IconTerminal2, IconBuildingSkyscraper, IconCopy, IconCheck, IconChevronLeft, IconExternalLink, IconCircleCheck, IconInfoCircle, IconSearch, IconServer, IconLoader2, IconRefresh, } from "@tabler/icons-react";
2
+ import { IconPlus, IconBrandSlack, IconBrandTelegram, IconBrandWhatsapp, IconBrandGoogleDrive, IconTerminal2, IconBuildingSkyscraper, IconCopy, IconCheck, IconChevronLeft, IconExternalLink, IconCircleCheck, IconInfoCircle, IconSearch, IconLoader2, IconRefresh, } from "@tabler/icons-react";
3
3
  import { useState, useCallback, useEffect, useMemo } from "react";
4
4
  import { agentNativePath } from "../api-path.js";
5
5
  import { Tooltip, TooltipContent, TooltipTrigger, } from "../components/ui/tooltip.js";
@@ -8,6 +8,7 @@ import { getDefaultMcpIntegrations } from "../resources/mcp-integration-catalog.
8
8
  import { McpIntegrationDialog } from "../resources/McpIntegrationDialog.js";
9
9
  import { McpIntegrationLogo } from "../resources/McpIntegrationLogo.js";
10
10
  import { useCreateMcpServer, useDeleteMcpServer, useMcpServers, useReconnectMcpServer, } from "../resources/use-mcp-servers.js";
11
+ import { cn } from "../utils.js";
11
12
  import { IntegrationGrid } from "./IntegrationGrid.js";
12
13
  import { useIntegrationStatus, } from "./useIntegrationStatus.js";
13
14
  import { isNonPublicWebhookUrl } from "./webhook-url.js";
@@ -264,12 +265,13 @@ function McpServerStatus({ server, onReconnect, reconnecting = false, reconnectE
264
265
  }
265
266
  return (_jsxs("span", { className: "inline-flex items-center gap-1.5 text-xs text-muted-foreground", children: [_jsx("span", { className: "size-1.5 rounded-full bg-muted-foreground/50" }), "Status unknown"] }));
266
267
  }
267
- function McpIntegrationsSection({ query }) {
268
+ export function McpIntegrationsSection({ query, title, description, showTitle = true, showDescription = true, showHeader = true, className, onOAuthStart, oauthReturnPath, }) {
268
269
  const t = useT();
269
270
  const serversQuery = useMcpServers();
270
271
  const createServer = useCreateMcpServer();
271
272
  const deleteServer = useDeleteMcpServer();
272
273
  const reconnectServer = useReconnectMcpServer();
274
+ const [localQuery, setLocalQuery] = useState("");
273
275
  const [dialogOpen, setDialogOpen] = useState(false);
274
276
  const [initialIntegrationId, setInitialIntegrationId] = useState(null);
275
277
  const [connectIntegrationId, setConnectIntegrationId] = useState(null);
@@ -278,7 +280,8 @@ function McpIntegrationsSection({ query }) {
278
280
  const [reconnectingKey, setReconnectingKey] = useState(null);
279
281
  const [reconnectError, setReconnectError] = useState(null);
280
282
  const catalog = useMemo(() => getDefaultMcpIntegrations(), []);
281
- const normalizedQuery = query.trim().toLowerCase();
283
+ const activeQuery = query ?? localQuery;
284
+ const normalizedQuery = activeQuery.trim().toLowerCase();
282
285
  const filteredCatalog = useMemo(() => {
283
286
  if (!normalizedQuery)
284
287
  return catalog;
@@ -363,21 +366,23 @@ function McpIntegrationsSection({ query }) {
363
366
  setReconnectingKey(null);
364
367
  }
365
368
  }, [reconnectServer]);
366
- return (_jsxs("section", { "data-testid": "mcp-integrations", className: "space-y-5", children: [_jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between", children: [_jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(IconServer, { className: "size-4 text-muted-foreground" }), _jsx("h2", { className: "text-sm font-semibold text-foreground", children: "Agent integrations" })] }), _jsx("p", { className: "mt-1 text-xs leading-5 text-muted-foreground", children: "Give your agent tools and context from the services you use." })] }), _jsxs("button", { type: "button", onClick: () => openCatalog(), className: "inline-flex w-fit items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground transition-colors hover:bg-primary/90", children: [_jsx(IconPlus, { className: "size-3.5" }), "Add integration"] })] }), deleteError && (_jsx("p", { className: "border-y border-destructive/20 bg-destructive/5 py-3 text-xs text-destructive", children: deleteError })), serversQuery.isError ? (_jsx("p", { className: "border-y border-destructive/20 bg-destructive/5 py-3 text-xs text-destructive", children: "Could not load connected agent integrations. The catalog is still available." })) : serversQuery.isLoading ? (_jsxs("div", { className: "space-y-3 rounded-xl border border-border/70 bg-card px-4 py-4", children: [_jsx("div", { className: "h-5 w-1/2 animate-pulse rounded bg-muted" }), _jsx("div", { className: "h-5 w-3/4 animate-pulse rounded bg-muted" })] })) : servers.length > 0 && !normalizedQuery ? (_jsxs("section", { className: "space-y-2", children: [_jsx("h3", { className: "text-sm font-semibold text-foreground", children: "Installed" }), _jsx("div", { className: "overflow-hidden rounded-xl border border-border/70 bg-card text-card-foreground", children: _jsx("div", { className: "divide-y divide-border/60 px-4", children: servers.map((server) => {
367
- const key = `${server.scope}:${server.id}`;
368
- const canRemove = server.scope === "user" ||
369
- serversQuery.data?.role === "owner" ||
370
- serversQuery.data?.role === "admin";
371
- return (_jsxs("div", { className: "flex items-start gap-3 py-3.5", children: [_jsx("span", { className: "mt-0.5 flex size-9 shrink-0 items-center justify-center rounded-lg border border-border/70 bg-background text-muted-foreground", children: _jsx(IconServer, { className: "size-4" }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("span", { className: "truncate text-sm font-medium text-foreground", children: server.name }), _jsx("span", { className: "text-[11px] text-muted-foreground", children: server.scope === "user"
372
- ? t("mcpIntegrations.personal")
373
- : t("mcpIntegrations.sharedWithWorkspace") })] }), _jsx(McpServerStatus, { server: server, onReconnect: server.status.state === "error"
374
- ? () => server.authMode === "oauth"
375
- ? startMcpOAuthReconnect(server)
376
- : void reconnect(server)
377
- : undefined, reconnecting: reconnectingKey === key, reconnectError: reconnectError?.key === key
378
- ? reconnectError.message
379
- : undefined })] }), canRemove && (_jsx("button", { type: "button", onClick: () => void removeServer(server), disabled: deleteServer.isPending, className: "shrink-0 rounded-md border border-border px-2.5 py-1.5 text-xs font-medium text-foreground transition-colors hover:bg-accent disabled:opacity-50", children: deleteTarget === key ? "Confirm" : "Remove" }))] }, key));
380
- }) }) })] })) : null, filteredCatalog.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "mb-1 flex items-center justify-between gap-3", children: [_jsx("h3", { className: "text-sm font-semibold text-foreground", children: "Available integrations" }), _jsxs("span", { className: "text-xs text-muted-foreground", children: [filteredCatalog.length, " integrations"] })] }), _jsx(IntegrationGrid, { items: filteredCatalog.map((integration) => {
369
+ return (_jsxs("section", { "data-testid": "mcp-integrations", className: cn("space-y-5", className), children: [showHeader ? (_jsxs("div", { className: cn("flex flex-col gap-4 lg:flex-row lg:items-end", showTitle || showDescription
370
+ ? "lg:justify-between"
371
+ : "lg:justify-end"), children: [showTitle || showDescription ? (_jsxs("div", { children: [showTitle ? (_jsx("h1", { className: "text-2xl font-semibold tracking-[-0.04em] text-foreground", children: title ?? t("mcpIntegrations.menuLabel") })) : null, showDescription ? (_jsx("p", { className: "mt-1.5 max-w-2xl text-sm leading-6 text-muted-foreground", children: description ?? t("mcpIntegrations.menuDescription") })) : null] })) : null, _jsxs("div", { className: "flex w-full flex-col gap-2 sm:flex-row lg:w-auto", children: [_jsxs("label", { className: "relative block min-w-0 flex-1 lg:w-72", children: [_jsx(IconSearch, { className: "pointer-events-none absolute start-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { type: "search", value: activeQuery, onChange: (event) => setLocalQuery(event.target.value), placeholder: t("mcpIntegrations.searchPlaceholder"), "aria-label": t("mcpIntegrations.searchPlaceholder"), className: "h-9 w-full rounded-lg border border-border bg-background ps-9 pe-3 text-sm text-foreground outline-none transition-colors placeholder:text-muted-foreground focus:border-foreground/30 focus:ring-2 focus:ring-accent/40" })] }), _jsxs("button", { type: "button", onClick: () => openCatalog(), className: "inline-flex h-9 shrink-0 items-center justify-center gap-1.5 rounded-lg bg-primary px-3 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90", children: [_jsx(IconPlus, { className: "size-3.5" }), t("integrations.addIntegration")] })] })] })) : null, deleteError && (_jsx("p", { className: "border-y border-destructive/20 bg-destructive/5 py-3 text-xs text-destructive", children: deleteError })), serversQuery.isError ? (_jsx("p", { className: "border-y border-destructive/20 bg-destructive/5 py-3 text-xs text-destructive", children: "Could not load connected agent integrations. The catalog is still available." })) : serversQuery.isLoading ? (_jsxs("div", { className: "space-y-3 rounded-xl border border-border/70 bg-card px-4 py-4", children: [_jsx("div", { className: "h-5 w-1/2 animate-pulse rounded bg-muted" }), _jsx("div", { className: "h-5 w-3/4 animate-pulse rounded bg-muted" })] })) : servers.length > 0 && !normalizedQuery ? (_jsxs("section", { className: "space-y-2", children: [_jsx("h3", { className: "text-sm font-semibold text-foreground", children: "Installed" }), _jsx("div", { className: "grid gap-3 sm:grid-cols-2", children: servers.map((server) => {
372
+ const key = `${server.scope}:${server.id}`;
373
+ const canRemove = server.scope === "user" ||
374
+ serversQuery.data?.role === "owner" ||
375
+ serversQuery.data?.role === "admin";
376
+ return (_jsxs("div", { className: "flex min-w-0 items-start gap-3 rounded-2xl bg-card px-4 py-4", children: [_jsx(McpIntegrationLogo, { name: server.name, logoUrl: "", integrationId: server.name.toLowerCase(), className: "mt-0.5 size-9" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("span", { className: "truncate text-sm font-medium text-foreground", children: server.name }), _jsx("span", { className: "text-[11px] text-muted-foreground", children: server.scope === "user"
377
+ ? t("mcpIntegrations.personal")
378
+ : t("mcpIntegrations.sharedWithWorkspace") })] }), _jsx(McpServerStatus, { server: server, onReconnect: server.status.state === "error"
379
+ ? () => server.authMode === "oauth"
380
+ ? startMcpOAuthReconnect(server)
381
+ : void reconnect(server)
382
+ : undefined, reconnecting: reconnectingKey === key, reconnectError: reconnectError?.key === key
383
+ ? reconnectError.message
384
+ : undefined })] }), canRemove && (_jsx("button", { type: "button", onClick: () => void removeServer(server), disabled: deleteServer.isPending, className: "shrink-0 rounded-md border border-border px-2.5 py-1.5 text-xs font-medium text-foreground transition-colors hover:bg-accent disabled:opacity-50", children: deleteTarget === key ? "Confirm" : "Remove" }))] }, key));
385
+ }) })] })) : null, filteredCatalog.length > 0 && (_jsxs("div", { children: [_jsxs("div", { className: "mb-1 flex items-center justify-between gap-3", children: [_jsx("h3", { className: "text-sm font-semibold text-foreground", children: "Available integrations" }), _jsxs("span", { className: "text-xs text-muted-foreground", children: [filteredCatalog.length, " integrations"] })] }), _jsx(IntegrationGrid, { items: filteredCatalog.map((integration) => {
381
386
  const connected = connectedUrls.has(compareMcpUrl(integration.url));
382
387
  return {
383
388
  id: integration.id,
@@ -391,13 +396,16 @@ function McpIntegrationsSection({ query }) {
391
396
  : t("mcpIntegrations.connect"),
392
397
  onAction: () => openConnection(integration.id, connected),
393
398
  };
394
- }) })] })), filteredCatalog.length === 0 && normalizedQuery && (_jsxs("p", { className: "border-y border-border/60 py-4 text-xs text-muted-foreground", children: ["No agent integrations match \u201C", query, "\u201D."] })), _jsx(McpIntegrationDialog, { open: dialogOpen, onOpenChange: (open) => {
399
+ }) })] })), filteredCatalog.length === 0 && normalizedQuery && (_jsxs("p", { className: "border-y border-border/60 py-4 text-xs text-muted-foreground", children: ["No agent integrations match \u201C", activeQuery, "\u201D."] })), _jsx(McpIntegrationDialog, { open: dialogOpen, onOpenChange: (open) => {
395
400
  setDialogOpen(open);
396
401
  if (!open) {
397
402
  setInitialIntegrationId(null);
398
403
  setConnectIntegrationId(null);
399
404
  }
400
- }, initialIntegrationId: initialIntegrationId, connectIntegrationId: connectIntegrationId, defaultScope: "user", canCreateOrgMcp: canCreateOrgMcp, hasOrg: hasOrg, onCreateMcpServer: (args) => createServer.mutateAsync(args) })] }));
405
+ }, initialIntegrationId: initialIntegrationId, connectIntegrationId: connectIntegrationId, defaultScope: "user", canCreateOrgMcp: canCreateOrgMcp, hasOrg: hasOrg, onCreateMcpServer: (args) => createServer.mutateAsync(args), onOAuthStart: onOAuthStart, oauthReturnPath: oauthReturnPath })] }));
406
+ }
407
+ export function McpIntegrationsLanding({ title, description, ...props }) {
408
+ return (_jsx(McpIntegrationsSection, { ...props, title: title, description: description, showHeader: true }));
401
409
  }
402
410
  export function IntegrationsPanel() {
403
411
  const { statuses, loading, refetch } = useIntegrationStatus();
@@ -424,7 +432,7 @@ export function IntegrationsPanel() {
424
432
  if (selectedPlatform) {
425
433
  return (_jsx(IntegrationDetail, { platform: selectedPlatform, serverStatus: statusMap.get(selectedPlatform.id), onBack: () => setSelectedPlatform(null), onRefresh: refetch }));
426
434
  }
427
- return (_jsxs("div", { className: "w-full space-y-8", children: [_jsxs("div", { className: "flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-semibold tracking-[-0.04em] text-foreground", children: "Integrations" }), _jsx("p", { className: "mt-1.5 max-w-2xl text-sm leading-6 text-muted-foreground", children: "Connect the tools your agent can use to gather context, take action, and meet your team where work already happens." })] }), _jsxs("label", { className: "relative block w-full lg:max-w-xs", children: [_jsx(IconSearch, { className: "pointer-events-none absolute start-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { type: "search", value: query, onChange: (event) => setQuery(event.target.value), placeholder: "Search integrations", "aria-label": "Search integrations", className: "h-9 w-full rounded-lg border border-border bg-background ps-9 pe-3 text-sm text-foreground outline-none transition-colors placeholder:text-muted-foreground focus:border-foreground/30 focus:ring-2 focus:ring-accent/40" })] })] }), _jsx(McpIntegrationsSection, { query: normalizedQuery }), loading ? (_jsx("div", { className: "grid gap-3 sm:grid-cols-2", children: [0, 1, 2, 3].map((item) => (_jsx("div", { className: "h-28 animate-pulse rounded-xl border border-border bg-muted/30" }, item))) })) : (_jsxs(_Fragment, { children: [!normalizedQuery && connectedPlatforms.length > 0 && (_jsxs("section", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-baseline justify-between gap-3", children: [_jsx("h2", { className: "text-sm font-semibold text-foreground", children: "Connected" }), _jsxs("span", { className: "text-xs text-muted-foreground", children: [connectedPlatforms.length, " connected"] })] }), _jsx("div", { className: "grid gap-3 sm:grid-cols-2", children: _jsx(IntegrationGrid, { items: connectedPlatforms.map((platform) => {
435
+ return (_jsxs("div", { className: "w-full space-y-8", children: [_jsxs("div", { className: "flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-2xl font-semibold tracking-[-0.04em] text-foreground", children: "Integrations" }), _jsx("p", { className: "mt-1.5 max-w-2xl text-sm leading-6 text-muted-foreground", children: "Connect the tools your agent can use to gather context, take action, and meet your team where work already happens." })] }), _jsxs("label", { className: "relative block w-full lg:max-w-xs", children: [_jsx(IconSearch, { className: "pointer-events-none absolute start-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { type: "search", value: query, onChange: (event) => setQuery(event.target.value), placeholder: "Search integrations", "aria-label": "Search integrations", className: "h-9 w-full rounded-lg border border-border bg-background ps-9 pe-3 text-sm text-foreground outline-none transition-colors placeholder:text-muted-foreground focus:border-foreground/30 focus:ring-2 focus:ring-accent/40" })] })] }), _jsx(McpIntegrationsSection, { query: normalizedQuery, showHeader: false }), loading ? (_jsx("div", { className: "grid gap-3 sm:grid-cols-2", children: [0, 1, 2, 3].map((item) => (_jsx("div", { className: "h-28 animate-pulse rounded-xl border border-border bg-muted/30" }, item))) })) : (_jsxs(_Fragment, { children: [!normalizedQuery && connectedPlatforms.length > 0 && (_jsxs("section", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-baseline justify-between gap-3", children: [_jsx("h2", { className: "text-sm font-semibold text-foreground", children: "Connected" }), _jsxs("span", { className: "text-xs text-muted-foreground", children: [connectedPlatforms.length, " connected"] })] }), _jsx("div", { className: "grid gap-3 sm:grid-cols-2", children: _jsx(IntegrationGrid, { items: connectedPlatforms.map((platform) => {
428
436
  const status = statusMap.get(platform.id);
429
437
  return {
430
438
  id: platform.id,
@@ -1,4 +1,4 @@
1
- export { IntegrationsPanel } from "./IntegrationsPanel.js";
1
+ export { IntegrationsPanel, McpIntegrationsLanding, McpIntegrationsSection, type McpIntegrationsLandingProps, type McpIntegrationsSectionProps, } from "./IntegrationsPanel.js";
2
2
  export { IntegrationGrid, type IntegrationGridItem, type IntegrationGridProps, } from "./IntegrationGrid.js";
3
3
  export { IntegrationConnectionChoice, type IntegrationConnectionChoiceProps, } from "./IntegrationConnectionChoice.js";
4
4
  export { useIntegrationStatus } from "./useIntegrationStatus.js";
@@ -1,4 +1,4 @@
1
- export { IntegrationsPanel } from "./IntegrationsPanel.js";
1
+ export { IntegrationsPanel, McpIntegrationsLanding, McpIntegrationsSection, } from "./IntegrationsPanel.js";
2
2
  export { IntegrationGrid, } from "./IntegrationGrid.js";
3
3
  export { IntegrationConnectionChoice, } from "./IntegrationConnectionChoice.js";
4
4
  export { useIntegrationStatus } from "./useIntegrationStatus.js";
@@ -453,7 +453,7 @@ export function McpIntegrationDialog({ open, onOpenChange, initialIntegrationId
453
453
  ? t("mcpIntegrations.workspaceAdminRequired")
454
454
  : undefined, personalOnlyReason: !supportsMcpIntegrationOrganizationScope(selected)
455
455
  ? t("mcpIntegrations.personalOnlyDescription")
456
- : undefined, busy: busy, onPersonal: () => connectPersonal(selected), onWorkspace: () => connectWorkspace(selected) })] })) : mode === "catalog" ? (_jsxs(_Fragment, { children: [_jsxs(DialogHeader, { className: "shrink-0 border-b border-border px-7 pb-5 pe-14 pt-7 sm:px-10", children: [_jsx(DialogTitle, { children: t("mcpIntegrations.title") }), _jsx(DialogDescription, { children: t("mcpIntegrations.description", {
456
+ : undefined, busy: busy, onPersonal: () => connectPersonal(selected), onWorkspace: () => connectWorkspace(selected) })] })) : mode === "catalog" ? (_jsxs(_Fragment, { children: [_jsxs(DialogHeader, { className: "shrink-0 px-7 pb-5 pe-14 pt-7 sm:px-10", children: [_jsx(DialogTitle, { children: t("mcpIntegrations.title") }), _jsx(DialogDescription, { children: t("mcpIntegrations.description", {
457
457
  count: defaultIntegrations.length,
458
458
  }) })] }), _jsx("div", { className: "shrink-0 px-7 pb-5 sm:px-10", children: _jsxs("div", { className: "mx-auto flex w-full max-w-5xl flex-col gap-3 sm:flex-row", children: [_jsxs("label", { className: "relative min-w-0 flex-1", children: [_jsx(IconSearch, { className: "pointer-events-none absolute start-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" }), _jsx("input", { value: query, onChange: (event) => setQuery(event.target.value), className: "h-9 w-full rounded-md border border-border bg-background pe-3 ps-8 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/50 focus:ring-1 focus:ring-ring", placeholder: t("mcpIntegrations.searchPlaceholder") })] }), _jsx("button", { type: "button", onClick: () => openForm(null), className: cn("inline-flex h-9 items-center justify-center gap-1.5 rounded-md border border-border bg-background px-3 text-[12px] font-medium text-foreground hover:bg-accent", !customIntegrationEnabled && "hidden"), children: t("mcpIntegrations.addYourOwn") })] }) }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto px-7 pb-10 pt-7 sm:px-10", children: _jsxs("div", { className: "mx-auto w-full max-w-5xl", children: [error && (_jsx("div", { className: "mb-3 rounded-md border border-destructive/20 bg-destructive/5 px-3 py-2 text-[12px] leading-relaxed text-destructive", children: error })), !mcpServersQuery.isSuccess && !mcpServersQuery.isError ? (_jsx("div", { role: "status", className: "mb-3 rounded-md border border-border bg-muted/30 px-3 py-2 text-[12px] leading-relaxed text-muted-foreground", children: t("mcpIntegrations.loadingScopeMetadata") })) : null, _jsx(IntegrationGrid, { items: filteredIntegrations.map((integration) => {
459
459
  const connected = connectedUrls.has(compareUrl(integration.url));
@@ -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;
@@ -28,6 +28,6 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
28
28
  } | {
29
29
  count?: undefined;
30
30
  updated?: undefined;
31
- ok: boolean;
32
31
  error?: undefined;
32
+ ok: boolean;
33
33
  }>>;
@@ -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,11 +48,11 @@ 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
- ok: boolean;
55
54
  error?: undefined;
55
+ ok: boolean;
56
56
  }>;
57
57
  /** POST /_agent-native/resources/upload — upload a file as a resource */
58
58
  export declare function handleUploadResource(event: any): Promise<import("./store.js").Resource | {
@@ -73,10 +73,10 @@ 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
79
  storageSetupRequired?: undefined;
79
- error?: undefined;
80
80
  } | {
81
81
  error: string;
82
82
  storageSetupRequired: boolean;
@@ -157,8 +157,26 @@ function injectDefaultSocialImageMeta(html, imageUrl) {
157
157
  return html;
158
158
  return html.slice(0, headCloseIdx) + tags.join("") + html.slice(headCloseIdx);
159
159
  }
160
+ /**
161
+ * A "not found" shell is exactly as impersonal as a 200 shell, and leaving it
162
+ * uncached is expensive in a way that is invisible until it is not: every dead
163
+ * link, stale bookmark, renamed slug and crawler miss re-invoked the render
164
+ * function, and Netlify runs one request per container. Measured on
165
+ * www.agent-native.com, `/docs/<anything>` cost ~5s and cost the SAME ~5s on
166
+ * the very next identical request, because `no-cache` meant nothing was ever
167
+ * stored. Those invocations draw from the account-wide concurrency pool every
168
+ * other site shares, so one crawler walking dead links slowed unrelated apps.
169
+ *
170
+ * Only 404/410 join the shared policy. A 5xx is transient and must stay
171
+ * uncacheable — pinning one at the edge for the SWR window would turn a blip
172
+ * into an outage. 401/403 stay out because an auth-shaped response is the one
173
+ * error that could carry viewer-specific meaning.
174
+ */
175
+ const CACHEABLE_ERROR_STATUSES = new Set([404, 410]);
160
176
  function isSsrHtmlOrDataResponse(headers, status, pathname) {
161
- if (status < 200 || status >= 400)
177
+ if (status < 200)
178
+ return false;
179
+ if (status >= 400 && !CACHEABLE_ERROR_STATUSES.has(status))
162
180
  return false;
163
181
  const contentType = headers.get("content-type")?.toLowerCase() ?? "";
164
182
  if (contentType.includes("text/html"))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.168.6",
3
+ "version": "0.168.9",
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": {