@agent-native/core 0.153.9 → 0.153.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.
Files changed (36) hide show
  1. package/corpus/templates/analytics/app/pages/DataSources.tsx +2 -1
  2. package/corpus/templates/analytics/app/pages/monitoring/errors/IssueList.tsx +4 -2
  3. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +4 -2
  4. package/corpus/templates/clips/app/root.tsx +4 -1
  5. package/corpus/templates/clips/app/routes/share.$shareId.tsx +2 -2
  6. package/corpus/templates/clips/desktop/src/app.tsx +1 -1
  7. package/corpus/templates/design/app/components/design/DesignImportPanel.tsx +2 -1
  8. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +2 -1
  9. package/corpus/templates/plan/app/pages/PlansPage.tsx +5 -2
  10. package/dist/cli/skills-content/help.d.ts +1 -1
  11. package/dist/cli/skills-content/help.js +2 -1
  12. package/dist/cli/skills.js +2 -1
  13. package/dist/client/NewWorkspaceAppFlow.js +4 -1
  14. package/dist/client/agent-page/AgentTabsPage.d.ts +2 -2
  15. package/dist/client/agent-page/AgentTabsPage.js +12 -9
  16. package/dist/client/extensions/ExtensionsSidebarSection.js +2 -1
  17. package/dist/client/onboarding/FirstRunOnboarding.js +2 -1
  18. package/dist/client/org/TeamPage.js +14 -3
  19. package/dist/client/settings/SettingsPanel.js +26 -1
  20. package/dist/collab/awareness.d.ts +2 -2
  21. package/dist/collab/routes.d.ts +1 -1
  22. package/dist/collab/struct-routes.d.ts +1 -1
  23. package/dist/integrations/catalog.js +9 -8
  24. package/dist/notifications/routes.d.ts +1 -1
  25. package/dist/observability/routes.d.ts +3 -3
  26. package/dist/resources/handlers.d.ts +1 -1
  27. package/dist/secrets/routes.d.ts +9 -9
  28. package/dist/server/agent-chat-plugin.js +2 -2
  29. package/dist/server/onboarding-html.js +2 -1
  30. package/dist/shared/docs-url.d.ts +24 -0
  31. package/dist/shared/docs-url.js +39 -0
  32. package/dist/shared/index.d.ts +1 -0
  33. package/dist/shared/index.js +1 -0
  34. package/dist/templates/default/app/routes/_index.tsx +2 -1
  35. package/package.json +3 -3
  36. package/src/templates/default/app/routes/_index.tsx +2 -1
@@ -16,6 +16,7 @@ import {
16
16
  getDefaultMcpIntegrations,
17
17
  McpIntegrationLogo,
18
18
  } from "@agent-native/core/client/resources";
19
+ import { docsUrl } from "@agent-native/core/shared";
19
20
  import {
20
21
  IconCheck,
21
22
  IconChevronDown,
@@ -1903,7 +1904,7 @@ function FirstPartyAnalyticsCard() {
1903
1904
  each one happened.
1904
1905
  </p>
1905
1906
  <a
1906
- href="https://www.agent-native.com/docs/tracking#error-capture"
1907
+ href={docsUrl("tracking", { hash: "posthog-error-tracking" })}
1907
1908
  target="_blank"
1908
1909
  rel="noreferrer"
1909
1910
  className="mt-2 inline-flex items-center gap-1 font-medium text-primary hover:underline"
@@ -1,4 +1,5 @@
1
1
  import { CodeSurface } from "@agent-native/core/blocks";
2
+ import { docsUrl } from "@agent-native/core/shared";
2
3
  import {
3
4
  IconAlertTriangle,
4
5
  IconBug,
@@ -28,8 +29,9 @@ import {
28
29
  useStatusLabel,
29
30
  } from "./utils";
30
31
 
31
- const ERROR_CAPTURE_DOCS_URL =
32
- "https://www.agent-native.com/docs/tracking#error-capture";
32
+ const ERROR_CAPTURE_DOCS_URL = docsUrl("tracking", {
33
+ hash: "posthog-error-tracking",
34
+ });
33
35
 
34
36
  const ERROR_CAPTURE_SNIPPET = `// Agent Native templates already call configureTracking().
35
37
  import { configureTracking, captureException } from "@agent-native/core/client/observability";
@@ -6,6 +6,7 @@ import {
6
6
  useBuilderConnectFlow,
7
7
  useBuilderStatus,
8
8
  } from "@agent-native/core/client/settings";
9
+ import { docsUrl } from "@agent-native/core/shared";
9
10
  import {
10
11
  IconCheck,
11
12
  IconChevronDown,
@@ -58,8 +59,9 @@ import { cn } from "@/lib/utils";
58
59
 
59
60
  type ReplayRange = "24h" | "7d" | "30d" | "90d" | "all";
60
61
 
61
- const SESSION_REPLAY_DOCS_URL =
62
- "https://www.agent-native.com/docs/tracking#session-replay";
62
+ const SESSION_REPLAY_DOCS_URL = docsUrl("tracking", {
63
+ hash: "session-replay",
64
+ });
63
65
 
64
66
  const S3_STORAGE_FIELDS = [
65
67
  {
@@ -19,6 +19,7 @@ import {
19
19
  } from "@agent-native/core/client/navigation";
20
20
  import { getThemeInitScript } from "@agent-native/core/client/ui";
21
21
  import { resolveLocaleFromRequest } from "@agent-native/core/server";
22
+ import { docsUrl } from "@agent-native/core/shared";
22
23
  import {
23
24
  IconHierarchy2,
24
25
  IconCheck,
@@ -225,7 +226,9 @@ const CLIPS_COMMAND_DOCS = [
225
226
  title: "Use the Chrome extension for browser logs",
226
227
  description:
227
228
  "Record a browser tab with redacted console logs, JavaScript exceptions, and fetch/XHR diagnostics.",
228
- href: "https://www.agent-native.com/docs/template-clips#browser-logs-and-developer-diagnostics",
229
+ href: docsUrl("template-clips-capture-everywhere", {
230
+ hash: "browser-logs-with-the-chrome-extension",
231
+ }),
229
232
  keywords: [
230
233
  "logs",
231
234
  "browser logs",
@@ -8,6 +8,7 @@ import {
8
8
  import { useSession, getBrowserTabId } from "@agent-native/core/client/hooks";
9
9
  import { useT } from "@agent-native/core/client/i18n";
10
10
  import { buildSignInReturnHref } from "@agent-native/core/client/ui";
11
+ import { docsUrl } from "@agent-native/core/shared";
11
12
  import {
12
13
  IconAlertTriangle,
13
14
  IconArrowLeft,
@@ -289,8 +290,7 @@ const STORAGE_KEY_PREFIX = "clips-share-pw-";
289
290
  const CLIPS_SOURCE_URL =
290
291
  "https://github.com/BuilderIO/agent-native/tree/main/templates/clips";
291
292
  const CLIPS_TEMPLATE_URL = "https://www.agent-native.com/templates/clips";
292
- const CLIPS_AGENT_DOCS_URL =
293
- "https://www.agent-native.com/docs/template-clips#agent-readable-clips";
293
+ const CLIPS_AGENT_DOCS_URL = docsUrl("template-clips-sharing-and-teams");
294
294
  const UPLOAD_STUCK_TIMEOUT_MS = 5 * 60 * 1000;
295
295
  const PROCESSING_STUCK_TIMEOUT_MS = 12 * 60 * 1000;
296
296
  const READY_MEDIA_SETTLE_POLL_MS = 20 * 1000;
@@ -377,7 +377,7 @@ const MIC_ON_KEY = "clips:mic-on";
377
377
  const SYSTEM_AUDIO_KEY = "clips:system-audio";
378
378
  const READINESS_REVIEWED_KEY = "clips:readiness-reviewed";
379
379
  const REWIND_DOCS_URL =
380
- "https://www.agent-native.com/docs/template-clips#agent-readable-clips";
380
+ "https://www.agent-native.com/docs/template-clips-capture-everywhere#rewind-quick-save";
381
381
 
382
382
  // Sensible defaults so the user never has to type a URL on first launch.
383
383
  // Dev builds point at the local dev server; production builds point at the
@@ -1,5 +1,6 @@
1
1
  import { useActionMutation } from "@agent-native/core/client/hooks";
2
2
  import { useFormatters, useT } from "@agent-native/core/client/i18n";
3
+ import { docsUrl } from "@agent-native/core/shared";
3
4
  import { parseFigmaFileKey } from "@shared/figma-url";
4
5
  import {
5
6
  IconBrandFigma,
@@ -696,7 +697,7 @@ export function DesignImportPanel(p: DesignImportPanelProps) {
696
697
  <p className="text-[11px] leading-snug text-muted-foreground">
697
698
  {t("designEditor.import.visualEditGuidance")}{" "}
698
699
  <a
699
- href="/docs/template-design"
700
+ href={docsUrl("template-design")}
700
701
  target="_blank"
701
702
  rel="noreferrer"
702
703
  className="font-medium text-foreground underline-offset-2 hover:underline"
@@ -1,4 +1,5 @@
1
1
  import { useT } from "@agent-native/core/client/i18n";
2
+ import { docsUrl } from "@agent-native/core/shared";
2
3
  import { VisualTweakControl } from "@agent-native/toolkit/design-tweaks";
3
4
  import type { TweakDefinition } from "@shared/api";
4
5
  import {
@@ -80,7 +81,7 @@ export function TweaksPanelContent({
80
81
  >
81
82
  {t("designEditor.tweaksHelp")}{" "}
82
83
  <a
83
- href="/docs/template-design#tweaks"
84
+ href={docsUrl("template-design")}
84
85
  target="_blank"
85
86
  rel="noreferrer"
86
87
  className="font-medium text-foreground/80 underline-offset-2 hover:text-foreground hover:underline"
@@ -23,6 +23,7 @@ import {
23
23
  ErrorReportActions,
24
24
  type ErrorReportDebugItem,
25
25
  } from "@agent-native/core/client/ui";
26
+ import { docsUrl } from "@agent-native/core/shared";
26
27
  import {
27
28
  useSetHeaderActions,
28
29
  useSetPageTitle,
@@ -388,8 +389,10 @@ const ENABLE_PLAN_STATUS_FEATURE = false;
388
389
  const GITHUB_LIGHT_CANVAS_BACKGROUND = "#ffffff";
389
390
  const GITHUB_DARK_CANVAS_BACKGROUND = "#0d1117";
390
391
  const LOCAL_PLAN_OWNER_EMAIL = "local@agent-native.local";
391
- const PLAN_DOCS_URL = "https://www.agent-native.com/docs/template-plan";
392
- const LOCAL_FILES_DOCS_URL = `${PLAN_DOCS_URL}#local-files`;
392
+ const PLAN_DOCS_URL = docsUrl("template-plan");
393
+ const LOCAL_FILES_DOCS_URL = docsUrl("template-plan-local-and-desktop", {
394
+ hash: "local-files",
395
+ });
393
396
  const AUTO_DEV_COMMENT_EMAILS = new Set(["dev@local.test", "dev@local"]);
394
397
  const CURRENT_USER_FALLBACK_NAME = "You";
395
398
  const CURRENT_USER_FALLBACK_INITIALS = "You";
@@ -1 +1 @@
1
- export declare const HELP = "npx @agent-native/core@latest skills\n\nUsage:\n npx @agent-native/core@latest skills list\n npx @agent-native/core@latest skills status [assets|content|rewind|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray|scaffold] [--client codex|claude-code|pi|all] [--scope user|project] [--json]\n npx @agent-native/core@latest skills update [assets|content|rewind|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray|scaffold] [--client codex|claude-code|pi|all] [--scope user|project] [--dry-run] [--json]\n npx @agent-native/core@latest skills add assets|content|rewind|design-exploration|visual-edit|visual-plan|visual-recap|visualize-repo|context-xray [--client codex|claude-code|cowork|cursor|opencode|github-copilot|all] [--scope user|project] [--mode hosted|local-files|self-hosted] [--mcp-url <url>] [--no-connect] [--with-github-action] [--yes] [--dry-run] [--json]\n npx @agent-native/core@latest skills add <manifest-or-app-dir|skill-repo> [--skill <name>] [--client ...] [--yes]\n\nExamples:\n npx @agent-native/core@latest skills add assets\n npx @agent-native/core@latest skills add rewind --client codex --scope user --yes\n npx @agent-native/core@latest skills add content --mode local-files\n npx @agent-native/core@latest skills add design-exploration\n npx @agent-native/core@latest skills add visual-edit\n npx @agent-native/core@latest skills add visual-plan\n npx @agent-native/core@latest skills add visual-recap\n npx @agent-native/core@latest skills add visualize-repo\n npx @agent-native/core@latest skills add visual-recap --with-github-action\n npx @agent-native/core@latest skills add visual-plan --mode local-files\n npx @agent-native/core@latest skills add visual-plan --mode self-hosted --mcp-url https://my-plan-app.example.com\n npx @agent-native/core@latest skills status visual-plan\n npx @agent-native/core@latest skills update visual-plan\n npx @agent-native/core@latest skills update scaffold --project\n npx @agent-native/core@latest skills add visual-plan --no-connect\n npx @agent-native/core@latest skills add context-xray --client all\n npx @agent-native/core@latest skills add assets --client claude-code\n npx @agent-native/core@latest skills add assets --mcp-url https://my-app.ngrok-free.dev\n npx @agent-native/core@latest skills add ./dist/assets-skill --client codex\n npx @agent-native/core@latest skills add BuilderIO/skills --client codex --scope project\n npx @agent-native/core@latest skills add BuilderIO/skills --with-github-action\n\nThe add command installs the SKILL.md instructions, registers the app-backed\nMCP connector, and then authenticates it in one step so you do not hit an OAuth\nwall on the first tool call. Hosted installs can configure Claude Code, Codex,\nClaude Cowork, Cursor, OpenCode, and GitHub Copilot / VS Code; local-files\ninstruction installs target the shared .agents skill path used by Codex, Pi,\nCursor, OpenCode, Copilot, and similar agents, plus Claude Code's native skill\npath when selected. Pass --client to narrow it. Authentication reuses\n\"npx @agent-native/core@latest connect\": OAuth-capable clients (Claude Code,\nCursor, OpenCode, GitHub Copilot / VS Code) get URL-only entries and authenticate\ninside that host, while Codex / Cowork run the browser device-code flow. In a\nnon-interactive shell or CI the auth step is skipped and the exact\n\"npx @agent-native/core@latest connect <url> --client all\" command is printed instead.\n\nRunning \"npx @agent-native/skills@latest add ...\" uses this same shared install\nflow with the broader BuilderIO skills catalog enabled. Pass --no-connect to\nregister MCP where possible without authenticating (leave auth to the host or run\n\"npx @agent-native/core@latest connect\" later). Pass --mcp-url to register that connector against\na custom origin (an ngrok tunnel, a local dev server, or a self-hosted\ndeployment) instead of the built-in hosted default \u2014 a bare origin gets the\nstandard /mcp path appended. Use app-skill pack for marketplace\nbundles and custom adapter output.\n\nWhen installing visual-plan, visual-recap, or visualize-repo interactively, the\nCLI asks where Plans artifacts should live: hosted Plans for shareable\nlinks/comments, local files for \"No sharing, all local.\", or a\nself-hosted/custom Plan app URL.\nPass --mode to choose directly. Local-files mode skips MCP registration and\nauth and installs instructions that default to a no-auth block catalog fetch,\nMDX folders, and the localhost bridge viewer.\n\nWhen installing content with --mode local-files, the CLI installs Content\ninstructions and writes or updates agent-native.json with repo-backed Markdown /\nMDX roots for docs, blog, content, and resources. Use a local Content app, Agent\nNative Desktop, or another trusted local bridge for Content actions to read and\nwrite those files.\n\nWhen installing visual-recap interactively, the CLI offers to add the optional PR\nVisual Recap GitHub Action. Pass --with-github-action to write it directly, then\nrun \"npx @agent-native/core@latest recap setup\" / \"npx @agent-native/core@latest recap doctor\" to configure and\nverify GitHub Actions. Docs: https://www.agent-native.com/docs/pr-visual-recap.\n\nThe status/update commands inspect copied Agent Native skill folders and refresh\ntheir instruction files from the current @agent-native/core package. In generated\napps/workspaces, \"skills update scaffold --project\" refreshes the framework\nskills copied into the scaffold and repairs AGENTS.md / CLAUDE.md and\n.agents/skills / .claude/skills compatibility links.";
1
+ export declare const HELP: string;
@@ -1,3 +1,4 @@
1
+ import { docsUrl } from "../../shared/docs-url.js";
1
2
  export const HELP = `npx @agent-native/core@latest skills
2
3
 
3
4
  Usage:
@@ -69,7 +70,7 @@ write those files.
69
70
  When installing visual-recap interactively, the CLI offers to add the optional PR
70
71
  Visual Recap GitHub Action. Pass --with-github-action to write it directly, then
71
72
  run "npx @agent-native/core@latest recap setup" / "npx @agent-native/core@latest recap doctor" to configure and
72
- verify GitHub Actions. Docs: https://www.agent-native.com/docs/pr-visual-recap.
73
+ verify GitHub Actions. Docs: ${docsUrl("pr-visual-recap")}.
73
74
 
74
75
  The status/update commands inspect copied Agent Native skill folders and refresh
75
76
  their instruction files from the current @agent-native/core package. In generated
@@ -10,6 +10,7 @@ import os from "node:os";
10
10
  import path from "node:path";
11
11
  import { fileURLToPath } from "node:url";
12
12
  import { MCP_LEGACY_ROUTE_PREFIX, MCP_PUBLIC_ROUTE_PREFIX, } from "../mcp/route-paths.js";
13
+ import { docsUrl } from "../shared/docs-url.js";
13
14
  import { buildAppSkillPack, ensureAppSkill, loadAppSkillManifest, normalizeAppSkillManifest, } from "./app-skill.js";
14
15
  import { resolveClients, runConnect, writeConnectClientPreferences, } from "./connect.js";
15
16
  import { CONTEXT_XRAY_SKILL_MD, installLocalContextXray, } from "./context-xray-local.js";
@@ -1720,7 +1721,7 @@ function prVisualRecapWorkflowPath(baseDir) {
1720
1721
  function prVisualRecapWorkflowDisplayPath() {
1721
1722
  return path.join(".github", "workflows", "pr-visual-recap.yml");
1722
1723
  }
1723
- const PR_VISUAL_RECAP_DOCS_URL = "https://www.agent-native.com/docs/pr-visual-recap";
1724
+ const PR_VISUAL_RECAP_DOCS_URL = docsUrl("pr-visual-recap");
1724
1725
  function prVisualRecapInstallCommand() {
1725
1726
  return "npx @agent-native/core@latest skills add visual-recap --with-github-action";
1726
1727
  }
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { IconAlertTriangle, IconArrowUpRight, IconBook, IconCheck, IconChevronDown, IconFileText, IconKey, } from "@tabler/icons-react";
3
3
  import { useEffect, useMemo, useState } from "react";
4
+ import { docsUrl } from "../shared/docs-url.js";
4
5
  import { getWorkspaceAppIdValidationError } from "../shared/workspace-app-id.js";
5
6
  import { sendToAgentChat } from "./agent-chat.js";
6
7
  import { agentNativePath, appBasePath } from "./api-path.js";
@@ -43,7 +44,9 @@ const ERROR_FAILURE_REASONS = new Set([
43
44
  "builder-not-connected",
44
45
  "credential-store-unavailable",
45
46
  ]);
46
- const LOCAL_APP_DOCS_URL = "https://agent-native.com/docs/multi-app-workspace#adding-a-new-app";
47
+ const LOCAL_APP_DOCS_URL = docsUrl("multi-app-workspace", {
48
+ hash: "adding-a-new-app",
49
+ });
47
50
  function isErrorFailureReason(reason) {
48
51
  return !!reason && ERROR_FAILURE_REASONS.has(reason);
49
52
  }
@@ -5,8 +5,8 @@ import type { AgentPageTabProps } from "./types.js";
5
5
  export declare const AGENT_RESOURCE_DOCS_HREF: Record<ResourceView, string>;
6
6
  export declare function ConnectionsTab({ canManageOrg, }?: Partial<AgentPageTabProps>): import("react").JSX.Element;
7
7
  export declare const AGENT_ACCESS_DOCS_HREF: {
8
- readonly mcp: "https://agent-native.com/docs/mcp-protocol";
9
- readonly a2a: "https://agent-native.com/docs/a2a-protocol";
8
+ readonly mcp: string;
9
+ readonly a2a: string;
10
10
  };
11
11
  export interface AgentPageExtraTabContext extends AgentPageTabProps {
12
12
  scopeControl: ReactNode;
@@ -1,6 +1,7 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { IconBook2, IconBolt, IconChecklist, IconExternalLink, IconFolder, IconHistory, IconHelpCircle, IconHierarchy2, IconNotes, IconPlugConnected, IconTopologyRing2, IconSearch, IconSettings, IconShieldLock, IconX, } from "@tabler/icons-react";
3
3
  import { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState, } from "react";
4
+ import { docsUrl } from "../../shared/docs-url.js";
4
5
  import { MCP_CONNECT_GUIDES, MCP_CONNECT_MCP_URL_TEMPLATE, MCP_STATIC_TOKEN_FALLBACK, interpolateMcpConnectTemplate, } from "../../shared/mcp-connect-content.js";
5
6
  import { appPath } from "../api-path.js";
6
7
  import { useT } from "../i18n.js";
@@ -61,13 +62,15 @@ function EmptySlot({ label }) {
61
62
  return (_jsx("div", { className: "flex min-h-[220px] items-center justify-center rounded-lg border border-dashed border-border/70 bg-muted/10", children: _jsx("span", { className: "sr-only", children: label }) }));
62
63
  }
63
64
  export const AGENT_RESOURCE_DOCS_HREF = {
64
- files: "https://agent-native.com/docs/agent-resources#resources-tab",
65
- instructions: "https://agent-native.com/docs/agent-resources#agents-md",
66
- agents: "https://agent-native.com/docs/agent-resources#custom-agents",
67
- memory: "https://agent-native.com/docs/agent-resources#memory",
68
- skills: "https://agent-native.com/docs/skills-guide",
69
- learnings: "https://agent-native.com/docs/agent-resources#memory",
70
- "remote-agents": "https://agent-native.com/docs/agent-resources#remote-vs-custom-agents",
65
+ files: docsUrl("agent-resources", { hash: "resources-tab" }),
66
+ instructions: docsUrl("agent-resources", { hash: "agents-md" }),
67
+ agents: docsUrl("agent-resources", { hash: "custom-agents" }),
68
+ memory: docsUrl("agent-resources", { hash: "memory" }),
69
+ skills: docsUrl("skills-guide"),
70
+ learnings: docsUrl("agent-resources", { hash: "memory" }),
71
+ "remote-agents": docsUrl("agent-resources", {
72
+ hash: "remote-vs-custom-agents",
73
+ }),
71
74
  };
72
75
  const RESOURCE_TAB_COPY = {
73
76
  files: {
@@ -181,8 +184,8 @@ export function ConnectionsTab({ canManageOrg, } = {}) {
181
184
  : "Agent integrations shared with this workspace will appear here." }))] }, section.scope))) })), _jsx(McpIntegrationDialog, { open: dialogOpen, onOpenChange: setDialogOpen, defaultScope: "user", canCreateOrgMcp: canCreateOrgMcp, hasOrg: hasOrg, onCreateMcpServer: onCreateMcpServer })] }) }));
182
185
  }
183
186
  export const AGENT_ACCESS_DOCS_HREF = {
184
- mcp: "https://agent-native.com/docs/mcp-protocol",
185
- a2a: "https://agent-native.com/docs/a2a-protocol",
187
+ mcp: docsUrl("mcp-protocol"),
188
+ a2a: docsUrl("a2a-protocol"),
186
189
  };
187
190
  function CopyField({ label, value, docsHref, docsLabel }) {
188
191
  const [copied, setCopied] = useState(false);
@@ -4,6 +4,7 @@ import { useQuery, useQueryClient } from "@tanstack/react-query";
4
4
  import { useState, useCallback, useMemo } from "react";
5
5
  import { Link, useLocation, useNavigate } from "react-router";
6
6
  import { extensionPath, isExtensionPathname } from "../../extensions/path.js";
7
+ import { docsUrl } from "../../shared/docs-url.js";
7
8
  import { sendToAgentChat } from "../agent-chat.js";
8
9
  import { agentNativePath } from "../api-path.js";
9
10
  import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "../components/ui/dropdown-menu.js";
@@ -665,7 +666,7 @@ export function ExtensionsSidebarSection() {
665
666
  };
666
667
  return (_jsx(TooltipProvider, { delayDuration: 200, children: _jsxs("div", { className: "relative min-w-0 py-1", children: [_jsxs("div", { className: cn("group/extensions-section relative flex w-full min-w-0 items-center rounded-md text-sm font-medium transition-[opacity,color,background-color] hover:text-primary", location.pathname.startsWith("/extensions")
667
668
  ? "text-sidebar-accent-foreground"
668
- : "text-muted-foreground hover:bg-sidebar-accent/50", extensionsOpen && sortedTools.length > 0 && "mb-1"), children: [_jsx("button", { type: "button", onClick: toggleExtensionsOpen, className: "absolute inset-0 rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", "aria-label": extensionsOpen ? copy.collapse : copy.expand, "aria-expanded": extensionsOpen }), _jsxs("div", { className: "pointer-events-none relative z-10 flex min-w-0 flex-1 items-center gap-2 px-3 py-1.5 pr-20", children: [_jsx(IconTool, { className: "h-4 w-4 shrink-0" }), _jsxs(HoverCard, { openDelay: 1200, closeDelay: 200, children: [_jsx(HoverCardTrigger, { asChild: true, children: _jsx("span", { className: "pointer-events-auto min-w-0 select-none truncate", onClick: toggleExtensionsOpen, children: copy.title }) }), _jsxs(HoverCardContent, { side: "top", align: "start", sideOffset: 8, className: "w-72 space-y-3 p-3", children: [_jsxs("div", { children: [_jsx("p", { className: "text-sm font-semibold text-foreground", children: copy.title }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: copy.description })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Link, { to: "/extensions", className: "inline-flex h-8 items-center rounded-md border px-2.5 text-xs font-medium text-foreground transition-colors hover:bg-accent", children: copy.open }), _jsx("a", { href: "https://agent-native.com/docs/extensions", target: "_blank", rel: "noopener noreferrer", className: "inline-flex h-8 items-center rounded-md px-2.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground", children: copy.learnMore })] })] })] })] }), _jsxs("div", { className: "absolute right-1 top-1/2 z-20 flex -translate-y-1/2 items-center", children: [_jsx(ExtensionSortMenu, { value: sortModeState, onChange: setExtensionSortMode, showHidden: showGloballyHidden, onShowHiddenChange: setShowGloballyHidden, copy: copy }), _jsxs(Popover, { open: showCreate, onOpenChange: setShowCreate, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "pointer-events-none inline-flex h-6 w-6 shrink-0 cursor-pointer items-center justify-center rounded-md text-muted-foreground/70 opacity-0 transition-[opacity,color,background-color] hover:bg-accent hover:text-accent-foreground focus-visible:pointer-events-auto focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring group-hover/extensions-section:pointer-events-auto group-hover/extensions-section:opacity-100 group-focus-within/extensions-section:pointer-events-auto group-focus-within/extensions-section:opacity-100 data-[state=open]:pointer-events-auto data-[state=open]:opacity-100", "aria-label": copy.newExtension, children: _jsx(IconPlus, { className: "h-3.5 w-3.5" }) }) }), _jsxs(PopoverContent, { side: "right", align: "start", collisionPadding: 8, className: "relative z-[360] w-[min(420px,calc(100vw-16px))] px-2 pb-2 pt-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-2 ps-1 pb-2", children: [_jsx("p", { className: "text-sm font-semibold text-foreground", children: copy.newExtension }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("a", { href: "https://agent-native.com/docs/extensions", target: "_blank", rel: "noopener noreferrer", className: "inline-flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", "aria-label": copy.learnMore, children: _jsx(IconHelpCircle, { className: "size-3" }) }) }), _jsx(TooltipContent, { children: copy.learnMore })] })] }), _jsx(PromptComposer, { autoFocus: true, placeholder: copy.createPlaceholder, draftScope: "extensions:sidebar-create", onSubmit: handleCreate })] })] }), _jsx("button", { type: "button", onClick: toggleExtensionsOpen, className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground/70 hover:bg-accent hover:text-foreground", "aria-label": extensionsOpen ? copy.collapse : copy.expand, "aria-expanded": extensionsOpen, children: _jsx(IconChevronDown, { className: cn("h-3.5 w-3.5 shrink-0 transition-transform", !extensionsOpen && "-rotate-90") }) })] })] }), extensionsOpen &&
669
+ : "text-muted-foreground hover:bg-sidebar-accent/50", extensionsOpen && sortedTools.length > 0 && "mb-1"), children: [_jsx("button", { type: "button", onClick: toggleExtensionsOpen, className: "absolute inset-0 rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", "aria-label": extensionsOpen ? copy.collapse : copy.expand, "aria-expanded": extensionsOpen }), _jsxs("div", { className: "pointer-events-none relative z-10 flex min-w-0 flex-1 items-center gap-2 px-3 py-1.5 pr-20", children: [_jsx(IconTool, { className: "h-4 w-4 shrink-0" }), _jsxs(HoverCard, { openDelay: 1200, closeDelay: 200, children: [_jsx(HoverCardTrigger, { asChild: true, children: _jsx("span", { className: "pointer-events-auto min-w-0 select-none truncate", onClick: toggleExtensionsOpen, children: copy.title }) }), _jsxs(HoverCardContent, { side: "top", align: "start", sideOffset: 8, className: "w-72 space-y-3 p-3", children: [_jsxs("div", { children: [_jsx("p", { className: "text-sm font-semibold text-foreground", children: copy.title }), _jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: copy.description })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Link, { to: "/extensions", className: "inline-flex h-8 items-center rounded-md border px-2.5 text-xs font-medium text-foreground transition-colors hover:bg-accent", children: copy.open }), _jsx("a", { href: docsUrl("extensions"), target: "_blank", rel: "noopener noreferrer", className: "inline-flex h-8 items-center rounded-md px-2.5 text-xs font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground", children: copy.learnMore })] })] })] })] }), _jsxs("div", { className: "absolute right-1 top-1/2 z-20 flex -translate-y-1/2 items-center", children: [_jsx(ExtensionSortMenu, { value: sortModeState, onChange: setExtensionSortMode, showHidden: showGloballyHidden, onShowHiddenChange: setShowGloballyHidden, copy: copy }), _jsxs(Popover, { open: showCreate, onOpenChange: setShowCreate, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "pointer-events-none inline-flex h-6 w-6 shrink-0 cursor-pointer items-center justify-center rounded-md text-muted-foreground/70 opacity-0 transition-[opacity,color,background-color] hover:bg-accent hover:text-accent-foreground focus-visible:pointer-events-auto focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring group-hover/extensions-section:pointer-events-auto group-hover/extensions-section:opacity-100 group-focus-within/extensions-section:pointer-events-auto group-focus-within/extensions-section:opacity-100 data-[state=open]:pointer-events-auto data-[state=open]:opacity-100", "aria-label": copy.newExtension, children: _jsx(IconPlus, { className: "h-3.5 w-3.5" }) }) }), _jsxs(PopoverContent, { side: "right", align: "start", collisionPadding: 8, className: "relative z-[360] w-[min(420px,calc(100vw-16px))] px-2 pb-2 pt-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-2 ps-1 pb-2", children: [_jsx("p", { className: "text-sm font-semibold text-foreground", children: copy.newExtension }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("a", { href: docsUrl("extensions"), target: "_blank", rel: "noopener noreferrer", className: "inline-flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", "aria-label": copy.learnMore, children: _jsx(IconHelpCircle, { className: "size-3" }) }) }), _jsx(TooltipContent, { children: copy.learnMore })] })] }), _jsx(PromptComposer, { autoFocus: true, placeholder: copy.createPlaceholder, draftScope: "extensions:sidebar-create", onSubmit: handleCreate })] })] }), _jsx("button", { type: "button", onClick: toggleExtensionsOpen, className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md text-muted-foreground/70 hover:bg-accent hover:text-foreground", "aria-label": extensionsOpen ? copy.collapse : copy.expand, "aria-expanded": extensionsOpen, children: _jsx(IconChevronDown, { className: cn("h-3.5 w-3.5 shrink-0 transition-transform", !extensionsOpen && "-rotate-90") }) })] })] }), extensionsOpen &&
669
670
  (extensionsQuery.isLoading ? (_jsx("div", { className: "min-w-0 space-y-0.5 px-0.5", children: [1, 2, 3].map((i) => (_jsx("div", { className: "flex items-center rounded-md px-2 py-1.5", children: _jsx("div", { className: "h-3 rounded bg-muted animate-pulse", style: { width: `${60 + i * 20}px` } }) }, i))) })) : extensionsQuery.isError ? (_jsx(ExtensionQueryErrorState, { compact: true, message: copy.loadError, onRetry: () => void extensionsQuery.refetch(), retrying: extensionsQuery.isFetching })) : sortedTools.length === 0 ? null : (_jsxs("div", { className: "min-w-0 space-y-0.5 px-0.5", children: [visibleTools.map((extension) => {
670
671
  const isActive = isExtensionPathname(location.pathname, extension.id);
671
672
  const isFav = favoriteIds.has(extension.id);
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Skeleton } from "@agent-native/toolkit/ui/skeleton";
3
3
  import { IconArrowRight, IconBrandGithub, IconCheck, IconExternalLink, IconInfoCircle, IconKey, IconLoader2, IconSearch, } from "@tabler/icons-react";
4
4
  import React, { useMemo, useState } from "react";
5
+ import { docsUrl } from "../../shared/docs-url.js";
5
6
  import { appPath } from "../api-path.js";
6
7
  import { Tooltip, TooltipContent, TooltipTrigger, } from "../components/ui/tooltip.js";
7
8
  import { IntegrationGrid } from "../integrations/IntegrationGrid.js";
@@ -176,7 +177,7 @@ export function FirstRunOnboarding({ skipIntegrations = shouldSkipFirstRunIntegr
176
177
  return;
177
178
  event.preventDefault();
178
179
  setScreen("manual");
179
- }, children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-sm font-semibold", children: "Use my own keys" }), _jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "See what this app needs" })] }), _jsx(IconKey, { className: "text-muted-foreground", size: 17 })] }), _jsx(CapabilityList, { capabilities: profile.capabilities, compact: true, className: "mt-5 pt-3" })] })] }), import.meta.env.DEV ? (_jsxs("p", { "data-testid": "first-run-local-provider-note", className: "mx-auto max-w-2xl text-center text-[11px] leading-5 text-muted-foreground", children: ["Or set", " ", _jsx("code", { className: "rounded bg-muted px-1", children: "ANTHROPIC_API_KEY" }), " ", "or ", _jsx("code", { className: "rounded bg-muted px-1", children: "OPENAI_API_KEY" }), " ", "in ", _jsx("code", { className: "rounded bg-muted px-1", children: ".env" }), " to make that provider available to everyone using this app.", " ", _jsxs("a", { href: "https://agent-native.com/docs/environment-variables", target: "_blank", rel: "noreferrer", className: "inline-flex items-center gap-1 text-foreground underline decoration-border underline-offset-2 hover:decoration-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: ["Read the setup guide", _jsx(IconExternalLink, { size: 12 })] })] })) : null] }) }));
180
+ }, children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-sm font-semibold", children: "Use my own keys" }), _jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "See what this app needs" })] }), _jsx(IconKey, { className: "text-muted-foreground", size: 17 })] }), _jsx(CapabilityList, { capabilities: profile.capabilities, compact: true, className: "mt-5 pt-3" })] })] }), import.meta.env.DEV ? (_jsxs("p", { "data-testid": "first-run-local-provider-note", className: "mx-auto max-w-2xl text-center text-[11px] leading-5 text-muted-foreground", children: ["Or set", " ", _jsx("code", { className: "rounded bg-muted px-1", children: "ANTHROPIC_API_KEY" }), " ", "or ", _jsx("code", { className: "rounded bg-muted px-1", children: "OPENAI_API_KEY" }), " ", "in ", _jsx("code", { className: "rounded bg-muted px-1", children: ".env" }), " to make that provider available to everyone using this app.", " ", _jsxs("a", { href: docsUrl("environment-variables"), target: "_blank", rel: "noreferrer", className: "inline-flex items-center gap-1 text-foreground underline decoration-border underline-offset-2 hover:decoration-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: ["Read the setup guide", _jsx(IconExternalLink, { size: 12 })] })] })) : null] }) }));
180
181
  }
181
182
  if (screen === "manual") {
182
183
  return (_jsx(OnboardingShell, { profile: profile, screen: "choice", children: _jsxs("div", { className: "mx-auto flex w-full max-w-xl flex-col gap-4", children: [_jsxs("div", { children: [_jsx("button", { type: "button", className: "mb-4 text-xs text-muted-foreground hover:text-foreground", onClick: () => setScreen("choice"), children: "Back" }), _jsx("h1", { className: "text-xl font-semibold tracking-[-0.04em] sm:text-2xl", children: "Your keys" })] }), _jsxs("div", { className: "rounded-xl bg-muted/35 p-4", children: [_jsx(CapabilityList, { capabilities: profile.capabilities }), _jsxs("div", { className: "mt-5 flex flex-col-reverse gap-2 pt-4 sm:flex-row sm:justify-between", children: [_jsx("button", { type: "button", className: secondaryButtonClass, onClick: () => setScreen("choice"), children: "Back" }), _jsxs("button", { type: "button", className: primaryButtonClass, onClick: handleOpenSettings, children: ["Open key settings", _jsx(IconArrowRight, { size: 15 })] }), _jsx("button", { type: "button", className: secondaryButtonClass, onClick: () => setScreen(skipIntegrations ? "ready" : "tools"), children: skipIntegrations ? "Continue" : "Continue to tools" })] })] })] }) }));
@@ -9,6 +9,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "
9
9
  import { Switch } from "@agent-native/toolkit/ui/switch";
10
10
  import { IconUserPlus, IconTrash, IconCrown, IconShieldCheck, IconLoader2, IconCheck, IconPencil, IconAt, IconX, IconKey, IconCopy, IconRefresh, IconEye, IconEyeOff, IconCloudUpload, IconFileImport, IconPlus, IconAlertTriangle, IconUsersGroup, IconHelpCircle, IconExternalLink, IconSearch, } from "@tabler/icons-react";
11
11
  import { forwardRef, useEffect, useMemo, useRef, useState, } from "react";
12
+ import { docsUrl } from "../../shared/docs-url.js";
12
13
  import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, } from "../components/ui/dialog.js";
13
14
  import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
14
15
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../components/ui/tooltip.js";
@@ -543,7 +544,10 @@ function DomainSettingsSection({ domain, ownerEmail, }) {
543
544
  onSuccess: () => setEditing(false),
544
545
  });
545
546
  }
546
- return (_jsx(SettingsRow, { id: "email-domain", label: "Email domain auto-join", description: _jsx(OrganizationDescription, { help: `Anyone who signs up with an email at this domain joins the organization automatically. Only your own email domain (${ownDomain || "—"}) can be used; free email providers are not allowed.`, docsUrl: "https://www.builder.io/c/docs/agent-native-authentication?utm_source=agent-native&utm_medium=product&utm_campaign=organization_settings&utm_content=domain_auto_join", children: "Automatically add members with your work email." }), control: !editing ? (_jsx("div", { className: "flex flex-wrap items-center justify-end gap-2", children: domain ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "inline-flex items-center gap-1.5 rounded-md border border-border bg-background px-2.5 py-1.5 text-sm", children: [_jsx(IconAt, { className: "h-3.5 w-3.5 text-muted-foreground" }), domain] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { type: "button", onClick: () => {
547
+ return (_jsx(SettingsRow, { id: "email-domain", label: "Email domain auto-join", description: _jsx(OrganizationDescription, { help: `Anyone who signs up with an email at this domain joins the organization automatically. Only your own email domain (${ownDomain || "—"}) can be used; free email providers are not allowed.`, docsUrl: docsUrl("organizations-teams-permissions", {
548
+ campaign: "organization_settings",
549
+ content: "domain_auto_join",
550
+ }), children: "Automatically add members with your work email." }), control: !editing ? (_jsx("div", { className: "flex flex-wrap items-center justify-end gap-2", children: domain ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "inline-flex items-center gap-1.5 rounded-md border border-border bg-background px-2.5 py-1.5 text-sm", children: [_jsx(IconAt, { className: "h-3.5 w-3.5 text-muted-foreground" }), domain] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { type: "button", onClick: () => {
547
551
  setDraft(domain);
548
552
  setEditing(true);
549
553
  }, className: "text-muted-foreground hover:text-foreground", children: _jsx(IconPencil, { size: 14 }) }) }), _jsx(TooltipContent, { children: "Edit domain" })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { type: "button", intent: "danger", emphasis: "ghost", disabled: setOrgDomain.isPending, onClick: () => setOrgDomain.mutate(null), className: "text-muted-foreground hover:text-destructive disabled:opacity-50", children: _jsx(IconX, { size: 14 }) }) }), _jsx(TooltipContent, { children: "Remove domain" })] })] })) : (_jsxs(Button, { type: "button", intent: "neutral", emphasis: "outline", onClick: () => {
@@ -570,7 +574,10 @@ function WorkspaceUrlSettingsSection({ workspaceUrl, }) {
570
574
  onSuccess: () => setEditing(false),
571
575
  });
572
576
  }
573
- return (_jsx(SettingsRow, { id: "workspace-url", label: "Workspace URL", description: _jsx(OrganizationDescription, { help: "Members who land on another deployment can be sent to this workspace URL instead of an empty app.", docsUrl: "https://www.builder.io/c/docs/agent-native-deployment?utm_source=agent-native&utm_medium=product&utm_campaign=organization_settings&utm_content=workspace_url", children: "Send members to this workspace from another deployment." }), control: !editing ? (_jsx("div", { className: "flex flex-wrap items-center justify-end gap-2", children: workspaceUrl ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "inline-flex max-w-72 items-center gap-1.5 truncate rounded-md border border-border bg-background px-2.5 py-1.5 text-sm", children: [_jsx(IconExternalLink, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }), _jsx("span", { className: "truncate", children: workspaceUrl })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { type: "button", onClick: () => {
577
+ return (_jsx(SettingsRow, { id: "workspace-url", label: "Workspace URL", description: _jsx(OrganizationDescription, { help: "Members who land on another deployment can be sent to this workspace URL instead of an empty app.", docsUrl: docsUrl("deployment", {
578
+ campaign: "organization_settings",
579
+ content: "workspace_url",
580
+ }), children: "Send members to this workspace from another deployment." }), control: !editing ? (_jsx("div", { className: "flex flex-wrap items-center justify-end gap-2", children: workspaceUrl ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: "inline-flex max-w-72 items-center gap-1.5 truncate rounded-md border border-border bg-background px-2.5 py-1.5 text-sm", children: [_jsx(IconExternalLink, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground" }), _jsx("span", { className: "truncate", children: workspaceUrl })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { type: "button", onClick: () => {
574
581
  setDraft(workspaceUrl);
575
582
  setEditing(true);
576
583
  }, className: "text-muted-foreground hover:text-foreground", children: _jsx(IconPencil, { size: 14 }) }) }), _jsx(TooltipContent, { children: "Edit workspace URL" })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { type: "button", intent: "danger", emphasis: "ghost", disabled: setWorkspaceUrl.isPending, onClick: () => setWorkspaceUrl.mutate(null), className: "text-muted-foreground hover:text-destructive disabled:opacity-50", children: _jsx(IconX, { size: 14 }) }) }), _jsx(TooltipContent, { children: "Remove workspace URL" })] })] })) : (_jsx(Button, { type: "button", intent: "neutral", emphasis: "outline", onClick: () => setEditing(true), className: "flex items-center gap-1.5 rounded-md border border-border px-2.5 py-1.5 text-xs font-medium hover:bg-accent/50", children: "Set URL" })) })) : (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("input", { type: "text", value: draft, onChange: (e) => setDraft(e.target.value), onKeyDown: (e) => {
@@ -591,7 +598,11 @@ function AuthProviderSettingsSection({ requiredAuthProvider, }) {
591
598
  }
592
599
  setAuthProvider.mutate(null);
593
600
  }
594
- return (_jsxs(_Fragment, { children: [_jsx(SettingsRow, { id: "organization-sign-in", label: "Organization sign-in", description: _jsx(OrganizationDescription, { help: "Require Google sign-in for every member. Enabling this revokes current sessions and rejects future password or non-Google sign-ins.", docsUrl: "https://www.builder.io/c/docs/agent-native-authentication?utm_source=agent-native&utm_medium=product&utm_campaign=organization_settings&utm_content=organization_sign_in", children: "Choose how members sign in." }), control: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { className: "text-sm font-medium", children: enabled ? "Google required" : "Google optional" }), _jsx(Switch, { checked: enabled, disabled: setAuthProvider.isPending, onCheckedChange: changeProvider, "aria-label": "Require Google sign-in" })] }), children: setAuthProvider.error ? (_jsx(ErrorText, { error: setAuthProvider.error })) : null }), _jsx(AlertDialog, { open: confirmOpen, onOpenChange: setConfirmOpen, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Require Google sign-in?" }), _jsx(AlertDialogDescription, { children: "Every current session in this organization will be revoked. Members must use their Google Workspace account the next time they sign in. Continue only after Google sign-in is configured for this app." })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: setAuthProvider.isPending, children: "Cancel" }), _jsx(AlertDialogAction, { disabled: setAuthProvider.isPending, onClick: () => {
601
+ return (_jsxs(_Fragment, { children: [_jsx(SettingsRow, { id: "organization-sign-in", label: "Organization sign-in", description: _jsx(OrganizationDescription, { help: "Require Google sign-in for every member. Enabling this revokes current sessions and rejects future password or non-Google sign-ins.", docsUrl: docsUrl("authentication", {
602
+ campaign: "organization_settings",
603
+ content: "organization_sign_in",
604
+ hash: "social-providers",
605
+ }), children: "Choose how members sign in." }), control: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("span", { className: "text-sm font-medium", children: enabled ? "Google required" : "Google optional" }), _jsx(Switch, { checked: enabled, disabled: setAuthProvider.isPending, onCheckedChange: changeProvider, "aria-label": "Require Google sign-in" })] }), children: setAuthProvider.error ? (_jsx(ErrorText, { error: setAuthProvider.error })) : null }), _jsx(AlertDialog, { open: confirmOpen, onOpenChange: setConfirmOpen, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Require Google sign-in?" }), _jsx(AlertDialogDescription, { children: "Every current session in this organization will be revoked. Members must use their Google Workspace account the next time they sign in. Continue only after Google sign-in is configured for this app." })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: setAuthProvider.isPending, children: "Cancel" }), _jsx(AlertDialogAction, { disabled: setAuthProvider.isPending, onClick: () => {
595
606
  setAuthProvider.mutate("google", {
596
607
  onSuccess: () => setConfirmOpen(false),
597
608
  });
@@ -6,6 +6,7 @@ import { IconChevronDown, IconChevronRight, IconCheck, IconExternalLink, IconBra
6
6
  import React, { Suspense, lazy, useState, useEffect, useCallback, useMemo, useRef, } from "react";
7
7
  import { PROVIDER_ENV_PLACEHOLDERS } from "../../agent/engine/provider-env-vars.js";
8
8
  import { buildSettingsRoute } from "../../navigation/index.js";
9
+ import { docsUrl } from "../../shared/docs-url.js";
9
10
  import { saveAgentEngineProviderSettings, setAgentEngineProvider, } from "../agent-engine-key.js";
10
11
  import { AgentWorkspaceContent } from "../agent-page/AgentWorkspaceContent.js";
11
12
  import { AGENT_PROVIDER_CATALOG, getAgentProviderOption, providerIdForEngine, } from "../agent-provider-catalog.js";
@@ -1088,7 +1089,31 @@ function SettingsPanelContent({ isDevMode, initialSection, sectionRequestKey, se
1088
1089
  const isWorkspacePage = isPage && sections.includes("hosting");
1089
1090
  return (_jsx(SettingsSurfaceProvider, { surface: surface, children: _jsxs("div", { className: cn(isPage ? "space-y-8" : "flex-1 min-h-0 overflow-y-auto p-3 space-y-2", className), style: isPage ? undefined : { overflowY: "auto" }, children: [showCapabilityStrip && (_jsx(CapabilityStatusStrip, { isDevMode: isDevMode, builderConnected: connected, builderLoading: builderLoading, builderBranchesAvailable: builderBranchesAvailable, onOpenLlm: () => openSettingsSection("llm", true) })), isPage &&
1090
1091
  ["llm", "app-models", "limits", "voice"].some((section) => shouldShowSection(section)) && (_jsxs(SettingsGroup, { title: "Agent", children: [shouldShowSection("llm") && (_jsx(LLMSectionInner, { builderFlow: builderFlow, builderLoading: builderLoading, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, grouped: true, open: openSection === "llm", onToggle: () => toggle("llm") })), shouldShowSection("app-models") && (_jsx(AppModelDefaultsSectionInner, { grouped: true, open: openSection === "app-models", onToggle: () => toggle("app-models") })), shouldShowSection("limits") && (_jsx(AgentLimitsSectionInner, { grouped: true, open: openSection === "limits", onToggle: () => toggle("limits") })), shouldShowSection("voice") && (_jsx(SettingsSection, { id: settingsSectionDomId("voice"), icon: _jsx(IconMicrophone, { size: 14 }), title: "Voice Transcription", subtitle: "Choose how voice input is transcribed.", grouped: true, flat: true, open: openSection === "voice", onToggle: () => toggle("voice"), children: _jsx(VoiceTranscriptionSection, { compact: true }) }))] })), isPage && agentAdditionalContent ? (_jsx(SettingsGroup, { title: "Notifications", children: agentAdditionalContent })) : null, isPage &&
1091
- ["automations", "background"].some((section) => shouldShowSection(section)) && (_jsxs(SettingsGroup, { title: "Agent workflows", children: [shouldShowSection("automations") && (_jsx(SettingsSection, { id: settingsSectionDomId("automations"), icon: _jsx(IconBolt, { size: 14 }), title: "Automations", subtitle: "Scheduled and event-triggered agent tasks.", grouped: true, flat: true, open: openSection === "automations", onToggle: () => toggle("automations"), children: _jsx(SettingsRow, { label: "Automations", description: "Schedule agent tasks or run them from events.", control: _jsxs("a", { href: "/settings/agent/automations", className: "inline-flex items-center gap-1 rounded-md border border-border px-3 py-1.5 text-sm font-medium text-foreground no-underline transition-colors hover:bg-accent/40", children: ["Open automations", _jsx(IconExternalLink, { size: 14 })] }) }) })), shouldShowSection("background") && (_jsx(SettingsSection, { id: settingsSectionDomId("background"), icon: _jsx(IconGitBranch, { size: 14 }), title: "Background Agent", subtitle: "Make code changes from production mode via Builder.", grouped: true, flat: true, connected: connected, open: openSection === "background", onToggle: () => toggle("background"), children: _jsx(SettingsRow, { label: "Background agent", description: "Make code changes from production mode via Builder.", control: _jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "background_agent_settings", trackingFlow: "background_agent", compact: true }) }) }))] })), isWorkspacePage && (_jsxs(SettingsGroup, { title: "Workspace", children: [shouldShowSection("demo-mode") && (_jsx(SettingsRow, { id: settingsSectionDomId("demo-mode"), label: "Demo mode", description: "Use sample data in this browser for presentations.", control: _jsx(DemoModeSection, { compact: true }) })), shouldShowSection("hosting") && (_jsx(SettingsRow, { id: settingsSectionDomId("hosting"), label: "Hosting", description: "Deploy the app to the cloud.", control: _jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [!connected && (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "hosting_settings", trackingFlow: "hosting", compact: true })), _jsx(ManualSetupCard, { title: "Set up manually", hint: "Deploy manually to Netlify, Vercel, Cloudflare, or any Nitro-supported target.", docsUrl: "https://www.builder.io/c/docs/agent-native-deployment?utm_source=agent-native&utm_medium=product&utm_campaign=onboarding&utm_content=deployment_settings", dim: connected, bare: true, popover: true, popoverLabel: "Manage", summaryContent: connected ? (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "hosting_settings", trackingFlow: "hosting" })) : undefined })] }) })), shouldShowSection("database") && (_jsx(SettingsRow, { id: settingsSectionDomId("database"), label: "Database", description: "Connect persistent app storage.", control: _jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [!connected && (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "database_settings", trackingFlow: "database", compact: true })), _jsx(ManualSetupCard, { title: "Set up manually", hint: "Set DATABASE_URL in your .env to connect a supported database.", docsUrl: "https://www.builder.io/c/docs/agent-native-database?utm_source=agent-native&utm_medium=product&utm_campaign=onboarding&utm_content=database_settings", dim: connected, bare: true, popover: true, popoverLabel: "Manage", summaryContent: connected ? (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "database_settings", trackingFlow: "database" })) : undefined })] }) })), shouldShowSection("uploads") && (_jsx(SettingsRow, { id: settingsSectionDomId("uploads"), label: "File uploads", description: "Store avatars and chat attachments.", control: _jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [!connected && (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "file_upload_settings", trackingFlow: "file_upload", compact: true })), _jsx(ManualSetupCard, { title: "Set up manually", hint: "Use an S3-compatible bucket with a stable public URL for durable chat attachments.", docsUrl: "https://www.builder.io/c/docs/agent-native-file-uploads?utm_source=agent-native&utm_medium=product&utm_campaign=onboarding&utm_content=file_upload_settings", dim: connected, bare: true, popover: true, popoverLabel: "Manage", summaryContent: connected ? (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "file_upload_settings", trackingFlow: "file_upload" })) : undefined, children: _jsx(FileStorageSettingsForm, {}) })] }) })), shouldShowSection("auth") && (_jsx(SettingsRow, { id: settingsSectionDomId("auth"), label: "Authentication", description: "Set up sign-in and access control.", control: _jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [!connected && (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "auth_settings", trackingFlow: "auth", compact: true })), _jsx(ManualSetupCard, { title: "Set up manually", hint: "Configure Better Auth and optional Google or GitHub providers.", docsUrl: "https://www.builder.io/c/docs/agent-native-authentication?utm_source=agent-native&utm_medium=product&utm_campaign=onboarding&utm_content=authentication_settings", dim: connected, bare: true, popover: true, popoverLabel: "Manage", summaryContent: connected ? (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "auth_settings", trackingFlow: "auth" })) : undefined })] }) }))] })), !isPage && shouldShowSection("llm") && (_jsx(LLMSectionInner, { builderFlow: builderFlow, builderLoading: builderLoading, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, open: openSection === "llm", onToggle: () => toggle("llm") })), !isPage && shouldShowSection("app-models") && (_jsx(AppModelDefaultsSectionInner, { open: openSection === "app-models", onToggle: () => toggle("app-models") })), !isPage && shouldShowSection("limits") && (_jsx(AgentLimitsSectionInner, { open: openSection === "limits", onToggle: () => toggle("limits") })), !isPage && shouldShowSection("voice") && (_jsx(SettingsSection, { id: settingsSectionDomId("voice"), icon: _jsx(IconMicrophone, { size: 14 }), title: "Voice Transcription", subtitle: "How the composer microphone turns your voice into text.", flat: true, open: openSection === "voice", onToggle: () => toggle("voice"), children: _jsx(VoiceTranscriptionSection, {}) })), !isPage && shouldShowSection("demo-mode") && (_jsx(SettingsSection, { id: settingsSectionDomId("demo-mode"), icon: _jsx(IconEyeOff, { size: 14 }), title: "Demo mode", subtitle: "Replace displayed emails with realistic fake data in this browser and reshape supported charts for presentations. Backend, agent integrations, and agent results stay real and access-scoped.", flat: true, open: openSection === "demo-mode", onToggle: () => toggle("demo-mode"), children: _jsx(DemoModeSection, {}) })), !isPage && shouldShowSection("automations") && (_jsx(SettingsSection, { id: settingsSectionDomId("automations"), icon: _jsx(IconBolt, { size: 14 }), title: "Automations", subtitle: "Scheduled and event-triggered agent tasks.", flat: true, open: openSection === "automations", onToggle: () => toggle("automations"), children: _jsx(AutomationsSection, {}) })), shouldShowSection("secrets") && (_jsx(SettingsSection, { id: settingsSectionDomId("secrets"), icon: _jsx(IconKey, { size: 14 }), title: "API keys", subtitle: "Service credentials and automation keys.", flat: true, open: openSection === "secrets", onToggle: () => toggle("secrets"), children: _jsx(SecretsSection, { focusKey: focusSecretKey }) })), !isPage && shouldShowSection("hosting") && (_jsx(SettingsSection, { id: settingsSectionDomId("hosting"), icon: _jsx(IconCloud, { size: 14 }), title: "Hosting", subtitle: "Deploy your app to the cloud.", flat: true, connected: connected, open: openSection === "hosting", onToggle: () => toggle("hosting"), children: _jsxs("div", { className: "space-y-2", children: [_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "hosting_settings", trackingFlow: "hosting" }), _jsx(ManualSetupCard, { hint: "Deploy manually to Netlify, Vercel, Cloudflare, or any Nitro-supported target.", docsUrl: "https://www.builder.io/c/docs/agent-native-deployment?utm_source=agent-native&utm_medium=product&utm_campaign=onboarding&utm_content=deployment_settings", dim: connected })] }) })), !isPage && shouldShowSection("database") && (_jsx(SettingsSection, { id: settingsSectionDomId("database"), icon: _jsx(IconDatabase, { size: 14 }), title: "Database", subtitle: "Connect a cloud database for persistent storage.", flat: true, connected: connected, open: openSection === "database", onToggle: () => toggle("database"), children: _jsxs("div", { className: "space-y-2", children: [_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "database_settings", trackingFlow: "database" }), _jsx(ManualSetupCard, { hint: "Set DATABASE_URL in your .env to connect Neon, Supabase, Turso, any Postgres/SQLite database, or local PGlite with pglite:./data/pglite.", docsUrl: "https://www.builder.io/c/docs/agent-native-database?utm_source=agent-native&utm_medium=product&utm_campaign=onboarding&utm_content=database_settings", dim: connected })] }) })), !isPage && shouldShowSection("uploads") && (_jsx(SettingsSection, { id: settingsSectionDomId("uploads"), icon: _jsx(IconUpload, { size: 14 }), title: "File uploads", subtitle: "Where user-uploaded files (avatars, chat attachments) are stored.", flat: true, connected: connected, open: openSection === "uploads", onToggle: () => toggle("uploads"), children: _jsxs("div", { className: "space-y-2", children: [_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "file_upload_settings", trackingFlow: "file_upload" }), _jsx(ManualSetupCard, { hint: "Object storage keeps uploaded files durable and their URLs reusable throughout the thread. Connect Builder or use an S3-compatible bucket below.", docsUrl: "https://www.builder.io/c/docs/agent-native-file-uploads?utm_source=agent-native&utm_medium=product&utm_campaign=onboarding&utm_content=file_upload_settings", dim: connected, children: _jsx(FileStorageSettingsForm, {}) })] }) })), !isPage && shouldShowSection("auth") && (_jsx(SettingsSection, { id: settingsSectionDomId("auth"), icon: _jsx(IconShield, { size: 14 }), title: "Authentication", subtitle: "Set up user authentication and access control.", flat: true, connected: connected, open: openSection === "auth", onToggle: () => toggle("auth"), children: _jsxs("div", { className: "space-y-2", children: [_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "auth_settings", trackingFlow: "auth" }), _jsx(ManualSetupCard, { hint: "Configure Better Auth with BETTER_AUTH_SECRET and optional Google/GitHub OAuth providers.", docsUrl: "https://www.builder.io/c/docs/agent-native-authentication?utm_source=agent-native&utm_medium=product&utm_campaign=onboarding&utm_content=authentication_settings", dim: connected })] }) })), shouldShowSection("email") && (_jsx(EmailSectionInner, { open: openSection === "email", onToggle: () => toggle("email") })), shouldShowSection("browser") && (_jsx(SettingsSection, { id: settingsSectionDomId("browser"), icon: _jsx(IconBrowser, { size: 14 }), title: "Browser Automation", subtitle: "Let agents control a real browser for web tasks.", flat: true, connected: builderConnectionOwnedExternally ? undefined : connected, open: openSection === "browser", onToggle: () => toggle("browser"), children: !builderConnectionOwnedExternally ? (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "browser_settings", trackingFlow: "browser_automation" })) : null })), !isPage &&
1092
+ ["automations", "background"].some((section) => shouldShowSection(section)) && (_jsxs(SettingsGroup, { title: "Agent workflows", children: [shouldShowSection("automations") && (_jsx(SettingsSection, { id: settingsSectionDomId("automations"), icon: _jsx(IconBolt, { size: 14 }), title: "Automations", subtitle: "Scheduled and event-triggered agent tasks.", grouped: true, flat: true, open: openSection === "automations", onToggle: () => toggle("automations"), children: _jsx(SettingsRow, { label: "Automations", description: "Schedule agent tasks or run them from events.", control: _jsxs("a", { href: "/settings/agent/automations", className: "inline-flex items-center gap-1 rounded-md border border-border px-3 py-1.5 text-sm font-medium text-foreground no-underline transition-colors hover:bg-accent/40", children: ["Open automations", _jsx(IconExternalLink, { size: 14 })] }) }) })), shouldShowSection("background") && (_jsx(SettingsSection, { id: settingsSectionDomId("background"), icon: _jsx(IconGitBranch, { size: 14 }), title: "Background Agent", subtitle: "Make code changes from production mode via Builder.", grouped: true, flat: true, connected: connected, open: openSection === "background", onToggle: () => toggle("background"), children: _jsx(SettingsRow, { label: "Background agent", description: "Make code changes from production mode via Builder.", control: _jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "background_agent_settings", trackingFlow: "background_agent", compact: true }) }) }))] })), isWorkspacePage && (_jsxs(SettingsGroup, { title: "Workspace", children: [shouldShowSection("demo-mode") && (_jsx(SettingsRow, { id: settingsSectionDomId("demo-mode"), label: "Demo mode", description: "Use sample data in this browser for presentations.", control: _jsx(DemoModeSection, { compact: true }) })), shouldShowSection("hosting") && (_jsx(SettingsRow, { id: settingsSectionDomId("hosting"), label: "Hosting", description: "Deploy the app to the cloud.", control: _jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [!connected && (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "hosting_settings", trackingFlow: "hosting", compact: true })), _jsx(ManualSetupCard, { title: "Set up manually", hint: "Deploy manually to Netlify, Vercel, Cloudflare, or any Nitro-supported target.", docsUrl: docsUrl("deployment", {
1093
+ campaign: "onboarding",
1094
+ content: "deployment_settings",
1095
+ }), dim: connected, bare: true, popover: true, popoverLabel: "Manage", summaryContent: connected ? (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "hosting_settings", trackingFlow: "hosting" })) : undefined })] }) })), shouldShowSection("database") && (_jsx(SettingsRow, { id: settingsSectionDomId("database"), label: "Database", description: "Connect persistent app storage.", control: _jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [!connected && (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "database_settings", trackingFlow: "database", compact: true })), _jsx(ManualSetupCard, { title: "Set up manually", hint: "Set DATABASE_URL in your .env to connect a supported database.", docsUrl: docsUrl("database", {
1096
+ campaign: "onboarding",
1097
+ content: "database_settings",
1098
+ }), dim: connected, bare: true, popover: true, popoverLabel: "Manage", summaryContent: connected ? (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "database_settings", trackingFlow: "database" })) : undefined })] }) })), shouldShowSection("uploads") && (_jsx(SettingsRow, { id: settingsSectionDomId("uploads"), label: "File uploads", description: "Store avatars and chat attachments.", control: _jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [!connected && (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "file_upload_settings", trackingFlow: "file_upload", compact: true })), _jsx(ManualSetupCard, { title: "Set up manually", hint: "Use an S3-compatible bucket with a stable public URL for durable chat attachments.", docsUrl: docsUrl("file-uploads", {
1099
+ campaign: "onboarding",
1100
+ content: "file_upload_settings",
1101
+ }), dim: connected, bare: true, popover: true, popoverLabel: "Manage", summaryContent: connected ? (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "file_upload_settings", trackingFlow: "file_upload" })) : undefined, children: _jsx(FileStorageSettingsForm, {}) })] }) })), shouldShowSection("auth") && (_jsx(SettingsRow, { id: settingsSectionDomId("auth"), label: "Authentication", description: "Set up sign-in and access control.", control: _jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [!connected && (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "auth_settings", trackingFlow: "auth", compact: true })), _jsx(ManualSetupCard, { title: "Set up manually", hint: "Configure Better Auth and optional Google or GitHub providers.", docsUrl: docsUrl("authentication", {
1102
+ campaign: "onboarding",
1103
+ content: "authentication_settings",
1104
+ }), dim: connected, bare: true, popover: true, popoverLabel: "Manage", summaryContent: connected ? (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "auth_settings", trackingFlow: "auth" })) : undefined })] }) }))] })), !isPage && shouldShowSection("llm") && (_jsx(LLMSectionInner, { builderFlow: builderFlow, builderLoading: builderLoading, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, open: openSection === "llm", onToggle: () => toggle("llm") })), !isPage && shouldShowSection("app-models") && (_jsx(AppModelDefaultsSectionInner, { open: openSection === "app-models", onToggle: () => toggle("app-models") })), !isPage && shouldShowSection("limits") && (_jsx(AgentLimitsSectionInner, { open: openSection === "limits", onToggle: () => toggle("limits") })), !isPage && shouldShowSection("voice") && (_jsx(SettingsSection, { id: settingsSectionDomId("voice"), icon: _jsx(IconMicrophone, { size: 14 }), title: "Voice Transcription", subtitle: "How the composer microphone turns your voice into text.", flat: true, open: openSection === "voice", onToggle: () => toggle("voice"), children: _jsx(VoiceTranscriptionSection, {}) })), !isPage && shouldShowSection("demo-mode") && (_jsx(SettingsSection, { id: settingsSectionDomId("demo-mode"), icon: _jsx(IconEyeOff, { size: 14 }), title: "Demo mode", subtitle: "Replace displayed emails with realistic fake data in this browser and reshape supported charts for presentations. Backend, agent integrations, and agent results stay real and access-scoped.", flat: true, open: openSection === "demo-mode", onToggle: () => toggle("demo-mode"), children: _jsx(DemoModeSection, {}) })), !isPage && shouldShowSection("automations") && (_jsx(SettingsSection, { id: settingsSectionDomId("automations"), icon: _jsx(IconBolt, { size: 14 }), title: "Automations", subtitle: "Scheduled and event-triggered agent tasks.", flat: true, open: openSection === "automations", onToggle: () => toggle("automations"), children: _jsx(AutomationsSection, {}) })), shouldShowSection("secrets") && (_jsx(SettingsSection, { id: settingsSectionDomId("secrets"), icon: _jsx(IconKey, { size: 14 }), title: "API keys", subtitle: "Service credentials and automation keys.", flat: true, open: openSection === "secrets", onToggle: () => toggle("secrets"), children: _jsx(SecretsSection, { focusKey: focusSecretKey }) })), !isPage && shouldShowSection("hosting") && (_jsx(SettingsSection, { id: settingsSectionDomId("hosting"), icon: _jsx(IconCloud, { size: 14 }), title: "Hosting", subtitle: "Deploy your app to the cloud.", flat: true, connected: connected, open: openSection === "hosting", onToggle: () => toggle("hosting"), children: _jsxs("div", { className: "space-y-2", children: [_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "hosting_settings", trackingFlow: "hosting" }), _jsx(ManualSetupCard, { hint: "Deploy manually to Netlify, Vercel, Cloudflare, or any Nitro-supported target.", docsUrl: docsUrl("deployment", {
1105
+ campaign: "onboarding",
1106
+ content: "deployment_settings",
1107
+ }), dim: connected })] }) })), !isPage && shouldShowSection("database") && (_jsx(SettingsSection, { id: settingsSectionDomId("database"), icon: _jsx(IconDatabase, { size: 14 }), title: "Database", subtitle: "Connect a cloud database for persistent storage.", flat: true, connected: connected, open: openSection === "database", onToggle: () => toggle("database"), children: _jsxs("div", { className: "space-y-2", children: [_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "database_settings", trackingFlow: "database" }), _jsx(ManualSetupCard, { hint: "Set DATABASE_URL in your .env to connect Neon, Supabase, Turso, any Postgres/SQLite database, or local PGlite with pglite:./data/pglite.", docsUrl: docsUrl("database", {
1108
+ campaign: "onboarding",
1109
+ content: "database_settings",
1110
+ }), dim: connected })] }) })), !isPage && shouldShowSection("uploads") && (_jsx(SettingsSection, { id: settingsSectionDomId("uploads"), icon: _jsx(IconUpload, { size: 14 }), title: "File uploads", subtitle: "Where user-uploaded files (avatars, chat attachments) are stored.", flat: true, connected: connected, open: openSection === "uploads", onToggle: () => toggle("uploads"), children: _jsxs("div", { className: "space-y-2", children: [_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "file_upload_settings", trackingFlow: "file_upload" }), _jsx(ManualSetupCard, { hint: "Object storage keeps uploaded files durable and their URLs reusable throughout the thread. Connect Builder or use an S3-compatible bucket below.", docsUrl: docsUrl("file-uploads", {
1111
+ campaign: "onboarding",
1112
+ content: "file_upload_settings",
1113
+ }), dim: connected, children: _jsx(FileStorageSettingsForm, {}) })] }) })), !isPage && shouldShowSection("auth") && (_jsx(SettingsSection, { id: settingsSectionDomId("auth"), icon: _jsx(IconShield, { size: 14 }), title: "Authentication", subtitle: "Set up user authentication and access control.", flat: true, connected: connected, open: openSection === "auth", onToggle: () => toggle("auth"), children: _jsxs("div", { className: "space-y-2", children: [_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "auth_settings", trackingFlow: "auth" }), _jsx(ManualSetupCard, { hint: "Configure Better Auth with BETTER_AUTH_SECRET and optional Google/GitHub OAuth providers.", docsUrl: docsUrl("authentication", {
1114
+ campaign: "onboarding",
1115
+ content: "authentication_settings",
1116
+ }), dim: connected })] }) })), shouldShowSection("email") && (_jsx(EmailSectionInner, { open: openSection === "email", onToggle: () => toggle("email") })), shouldShowSection("browser") && (_jsx(SettingsSection, { id: settingsSectionDomId("browser"), icon: _jsx(IconBrowser, { size: 14 }), title: "Browser Automation", subtitle: "Let agents control a real browser for web tasks.", flat: true, connected: builderConnectionOwnedExternally ? undefined : connected, open: openSection === "browser", onToggle: () => toggle("browser"), children: !builderConnectionOwnedExternally ? (_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "browser_settings", trackingFlow: "browser_automation" })) : null })), !isPage &&
1092
1117
  builderBranchesAvailable &&
1093
1118
  shouldShowSection("background") && (_jsx(SettingsSection, { id: settingsSectionDomId("background"), icon: _jsx(IconGitBranch, { size: 14 }), title: "Background Agent", subtitle: "Make code changes from production mode via Builder.", flat: true, connected: connected, open: openSection === "background", onToggle: () => toggle("background"), children: _jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "background_agent_settings", trackingFlow: "background_agent" }) })), shouldShowSection("integrations") && (_jsx(SettingsSection, { id: settingsSectionDomId("integrations"), icon: _jsx(IconPlugConnected, { size: 14 }), title: "Integrations", subtitle: "Connect messaging platforms and external services.", flat: true, open: openSection === "integrations", onToggle: () => toggle("integrations"), children: _jsx(Suspense, { fallback: null, children: _jsx(IntegrationsPanel, {}) }) })), shouldShowSection("usage") && (_jsx(SettingsSection, { id: settingsSectionDomId("usage"), icon: _jsx(IconCoin, { size: 14 }), title: "Usage", subtitle: "Track token consumption and estimated cost \u2014 broken down by chat, automations, and background jobs.", flat: true, open: openSection === "usage", onToggle: () => toggle("usage"), children: _jsx(UsageSection, {}) })), shouldShowSection("a2a") && (_jsx(SettingsSection, { id: settingsSectionDomId("a2a"), icon: _jsx(IconTopologyRing2, { size: 14 }), title: "Connected Agents (A2A)", subtitle: "Manage remote agents connected via the A2A protocol.", flat: true, open: openSection === "a2a", onToggle: () => toggle("a2a"), children: _jsx(AgentsSection, {}) }))] }) }));
1094
1119
  }
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
62
62
  error: string;
63
63
  states?: undefined;
64
64
  } | {
65
+ error?: undefined;
65
66
  states: {
66
67
  clientId: number;
67
68
  state: string;
68
69
  }[];
69
- error?: undefined;
70
70
  }>>;
71
71
  /**
72
72
  * GET /_agent-native/collab/:docId/users
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
77
77
  error: string;
78
78
  users?: undefined;
79
79
  } | {
80
+ error?: undefined;
80
81
  users: {
81
82
  clientId: number;
82
83
  lastSeen: number;
83
84
  }[];
84
- error?: undefined;
85
85
  }>>;
@@ -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;
@@ -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
- ok?: undefined;
17
16
  error: string;
17
+ ok?: undefined;
18
18
  } | {
19
19
  error?: undefined;
20
20
  ok: boolean;
@@ -5,6 +5,7 @@
5
5
  * Runtime behavior stays in adapters and plugins; consumers must use
6
6
  * availability and support maturity before offering a connection flow.
7
7
  */
8
+ import { docsUrl } from "../shared/docs-url.js";
8
9
  export const INTEGRATION_CATEGORIES = [
9
10
  "channel",
10
11
  "provider",
@@ -26,7 +27,7 @@ const BUILT_IN_CHANNEL_CATALOG = [
26
27
  "Managed installations select encrypted credentials by workspace; legacy manual installs should use SLACK_ALLOWED_TEAM_IDS.",
27
28
  ],
28
29
  documentation: {
29
- href: "/docs/messaging#slack",
30
+ href: docsUrl("messaging", { hash: "slack" }),
30
31
  externalHref: "https://api.slack.com/apps",
31
32
  externalLabel: "Open Slack apps",
32
33
  },
@@ -88,7 +89,7 @@ const BUILT_IN_CHANNEL_CATALOG = [
88
89
  "Production deployments must allowlist Microsoft Entra tenant IDs; proactive messaging without an inbound conversation reference is not implemented.",
89
90
  ],
90
91
  documentation: {
91
- href: "/docs/messaging#microsoft-teams",
92
+ href: docsUrl("messaging", { hash: "microsoft-teams" }),
92
93
  externalHref: "https://dev.botframework.com/",
93
94
  externalLabel: "Open Bot Framework",
94
95
  },
@@ -148,7 +149,7 @@ const BUILT_IN_CHANNEL_CATALOG = [
148
149
  "Interaction tokens are retained only while the queued task is active and normally expire after 15 minutes.",
149
150
  ],
150
151
  documentation: {
151
- href: "/docs/messaging#discord",
152
+ href: docsUrl("messaging", { hash: "discord" }),
152
153
  externalHref: "https://discord.com/developers/applications",
153
154
  externalLabel: "Open Discord applications",
154
155
  },
@@ -197,7 +198,7 @@ const BUILT_IN_CHANNEL_CATALOG = [
197
198
  "Webhook verification requires TELEGRAM_WEBHOOK_SECRET for production-safe setup.",
198
199
  ],
199
200
  documentation: {
200
- href: "/docs/messaging#telegram",
201
+ href: docsUrl("messaging", { hash: "telegram" }),
201
202
  externalHref: "https://t.me/BotFather",
202
203
  externalLabel: "Open BotFather",
203
204
  },
@@ -246,7 +247,7 @@ const BUILT_IN_CHANNEL_CATALOG = [
246
247
  "Meta pricing and the customer-service conversation window can limit replies; template-message flows are not implemented by this adapter.",
247
248
  ],
248
249
  documentation: {
249
- href: "/docs/messaging#whatsapp",
250
+ href: docsUrl("messaging", { hash: "whatsapp" }),
250
251
  externalHref: "https://developers.facebook.com/apps",
251
252
  externalLabel: "Open Meta developer console",
252
253
  },
@@ -303,7 +304,7 @@ const BUILT_IN_CHANNEL_CATALOG = [
303
304
  "Email replies preserve RFC email threads and reply-all when the agent was CC'd.",
304
305
  ],
305
306
  documentation: {
306
- href: "/docs/messaging#email",
307
+ href: docsUrl("messaging", { hash: "email" }),
307
308
  externalHref: "https://resend.com/webhooks",
308
309
  externalLabel: "Open Resend webhooks",
309
310
  },
@@ -363,7 +364,7 @@ const AUTOMATION_CATALOG = [
363
364
  "Use a configured webhook URL or n8n credential; never put an n8n URL or credential in an agent prompt.",
364
365
  ],
365
366
  documentation: {
366
- href: "/docs/automation-connectors#n8n",
367
+ href: docsUrl("automation-connectors", { hash: "n8n" }),
367
368
  externalHref: "https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.webhook/",
368
369
  externalLabel: "Open n8n Webhook docs",
369
370
  },
@@ -405,7 +406,7 @@ const AUTOMATION_CATALOG = [
405
406
  "Zapier MCP is a separately configured remote MCP connection with its own account and authorization flow.",
406
407
  ],
407
408
  documentation: {
408
- href: "/docs/automation-connectors#zapier",
409
+ href: docsUrl("automation-connectors", { hash: "zapier" }),
409
410
  externalHref: "https://docs.zapier.com/mcp/home",
410
411
  externalLabel: "Open Zapier MCP docs",
411
412
  },
@@ -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
  }>>;
@@ -42,22 +42,22 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
42
42
  avgEvalScore: number;
43
43
  } | {
44
44
  error?: undefined;
45
- ok?: undefined;
46
45
  summary: import("./types.js").TraceSummary;
47
46
  spans: import("./types.js").TraceSpan[];
48
47
  id?: undefined;
48
+ ok?: undefined;
49
49
  } | {
50
50
  error?: undefined;
51
- ok?: undefined;
52
51
  summary?: undefined;
53
52
  spans?: undefined;
54
53
  id: string;
55
- } | {
56
54
  ok?: undefined;
55
+ } | {
57
56
  summary?: undefined;
58
57
  spans?: undefined;
59
58
  id?: undefined;
60
59
  error: any;
60
+ ok?: undefined;
61
61
  } | {
62
62
  error?: undefined;
63
63
  summary?: undefined;
@@ -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
- ok?: undefined;
52
51
  error: string;
52
+ ok?: undefined;
53
53
  } | {
54
54
  error?: undefined;
55
55
  ok: boolean;
@@ -34,37 +34,37 @@ 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
- ok?: undefined;
38
37
  status?: undefined;
38
+ ok?: undefined;
39
39
  } | {
40
- error?: undefined;
41
40
  ok: boolean;
42
41
  status: string;
42
+ error?: undefined;
43
43
  } | {
44
- ok?: undefined;
45
44
  error: string;
46
45
  removed?: undefined;
46
+ ok?: undefined;
47
47
  } | {
48
- error?: undefined;
49
48
  ok: boolean;
50
49
  removed: boolean;
50
+ error?: undefined;
51
51
  }>>;
52
52
  /**
53
53
  * POST /_agent-native/secrets/:key/test — validate an optional candidate value
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;
58
57
  error: string;
59
58
  note?: undefined;
59
+ ok?: undefined;
60
60
  } | {
61
- error?: undefined;
62
61
  ok: boolean;
63
62
  note?: undefined;
64
- } | {
65
63
  error?: undefined;
64
+ } | {
66
65
  ok: boolean;
67
66
  note: string;
67
+ error?: undefined;
68
68
  } | {
69
69
  note?: undefined;
70
70
  ok: boolean;
@@ -95,11 +95,11 @@ export interface AdHocSecretPayload {
95
95
  export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
96
96
  error: string;
97
97
  } | {
98
- error?: undefined;
99
98
  ok: boolean;
100
99
  key: string;
101
- } | {
102
100
  error?: undefined;
101
+ } | {
103
102
  ok: boolean;
104
103
  removed: boolean;
104
+ error?: undefined;
105
105
  }>>;
@@ -34,6 +34,7 @@ import { getSkillNameFromPath } from "../resources/metadata.js";
34
34
  import { resourceList, resourceListAccessible, resourceGet, ensurePersonalDefaults, SHARED_OWNER, WORKSPACE_OWNER, } from "../resources/store.js";
35
35
  import { normalizeDatabaseToolsMode } from "../scripts/db/tool-mode.js";
36
36
  import { getSetting, putSetting } from "../settings/store.js";
37
+ import { docsUrl } from "../shared/docs-url.js";
37
38
  import { handleSharedThreadRequest, } from "./agent-chat/shared-thread.js";
38
39
  import { discoverAgents } from "./agent-discovery.js";
39
40
  import { resolveAgentRunOwnerContext, runWithAgentRunContext, seedBackgroundAgentRunOwnerContext, } from "./agent-run-context.js";
@@ -3510,8 +3511,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
3510
3511
  }
3511
3512
  const result = { skills };
3512
3513
  if (skills.length === 0) {
3513
- result.hint =
3514
- "No skills found. Add skill files under skills/ in Resources. Learn more: https://agent-native.com/docs/resources#skills";
3514
+ result.hint = `No skills found. Add skill files under skills/ in Resources. Learn more: ${docsUrl("agent-resources", { hash: "skills" })}`;
3515
3515
  }
3516
3516
  return result;
3517
3517
  }));
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { getLocaleInitScript } from "../localization/server.js";
10
10
  import { DEFAULT_LOCALE, LOCALE_METADATA, LOCALE_STORAGE_KEY, SUPPORTED_LOCALES, } from "../localization/shared.js";
11
+ import { docsUrl } from "../shared/docs-url.js";
11
12
  import { PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, } from "../shared/password-policy.js";
12
13
  import { signInJourneyInlineScript } from "../shared/sign-in-journey.js";
13
14
  import { AGENT_NATIVE_SOCIAL_IMAGE_ALT, AGENT_NATIVE_SOCIAL_IMAGE_HEIGHT, AGENT_NATIVE_SOCIAL_IMAGE_PATH, AGENT_NATIVE_SOCIAL_IMAGE_TYPE, AGENT_NATIVE_SOCIAL_IMAGE_WIDTH, withAgentNativeSocialImageCacheBuster, } from "../shared/social-meta.js";
@@ -1424,7 +1425,7 @@ ${localeMenuItemsHtml}
1424
1425
  <button type="button" class="btn-local-dev btn-primary" id="local-dev-btn" title="${esc(t("localDevDescription"))}"${i18nAttr("localDevButton")} data-i18n-title="localDevDescription" aria-describedby="local-dev-description">${esc(t("localDevButton"))}</button>
1425
1426
  <p class="local-dev-description" id="local-dev-description">
1426
1427
  <span${i18nAttr("localDevDescription")}>${esc(t("localDevDescription"))}</span>
1427
- <a class="local-dev-help" id="local-dev-help" href="https://www.agent-native.com/docs/authentication#local-development-sign-in" target="_blank" rel="noreferrer" aria-label="${esc(t("localDevHelp"))}" title="${esc(t("localDevHelp"))}" data-i18n-title="localDevHelp"${i18nAriaAttr("localDevHelp")}><span class="local-dev-help-glyph" aria-hidden="true">?</span></a>
1428
+ <a class="local-dev-help" id="local-dev-help" href="${docsUrl("authentication", { hash: "local-development-sign-in" })}" target="_blank" rel="noreferrer" aria-label="${esc(t("localDevHelp"))}" title="${esc(t("localDevHelp"))}" data-i18n-title="localDevHelp"${i18nAriaAttr("localDevHelp")}><span class="local-dev-help-glyph" aria-hidden="true">?</span></a>
1428
1429
  </p>
1429
1430
  <button type="button" class="local-dev-full-options" id="local-dev-full-options" hidden${i18nAttr("localDevFullOptions")}>${esc(t("localDevFullOptions"))}</button>
1430
1431
  <p class="msg error" id="local-dev-msg" role="status" aria-live="polite"></p>
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Absolute links into the public Agent-Native docs site.
3
+ *
4
+ * Call `docsUrl("content-slug")` at call sites so the path is visible inline
5
+ * (`docsUrl("template-design")` → `/docs/template-design`). Relative
6
+ * `/docs/...` paths resolve against the app origin and 404 — always use this
7
+ * helper for outbound docs links.
8
+ */
9
+ export declare const AGENT_NATIVE_DOCS_ORIGIN = "https://www.agent-native.com";
10
+ export type DocsUrlOptions = {
11
+ hash?: string;
12
+ /** UTM medium; defaults to `product` when any UTM field is set. */
13
+ medium?: string;
14
+ /** UTM campaign; defaults to `docs` when any UTM field is set. */
15
+ campaign?: string;
16
+ content?: string | null;
17
+ };
18
+ /**
19
+ * Build an absolute docs URL for a content slug (the MDX stem under
20
+ * `packages/core/docs/content/`).
21
+ *
22
+ * `getting-started` maps to `/docs` (the docs home).
23
+ */
24
+ export declare function docsUrl(slug: string, options?: DocsUrlOptions): string;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Absolute links into the public Agent-Native docs site.
3
+ *
4
+ * Call `docsUrl("content-slug")` at call sites so the path is visible inline
5
+ * (`docsUrl("template-design")` → `/docs/template-design`). Relative
6
+ * `/docs/...` paths resolve against the app origin and 404 — always use this
7
+ * helper for outbound docs links.
8
+ */
9
+ export const AGENT_NATIVE_DOCS_ORIGIN = "https://www.agent-native.com";
10
+ function applyDocsUtm(params, options) {
11
+ const wantsUtm = options.medium != null ||
12
+ options.campaign != null ||
13
+ options.content != null;
14
+ if (!wantsUtm)
15
+ return;
16
+ params.set("utm_source", "agent-native");
17
+ params.set("utm_medium", options.medium ?? "product");
18
+ params.set("utm_campaign", options.campaign ?? "docs");
19
+ if (options.content)
20
+ params.set("utm_content", options.content);
21
+ }
22
+ /**
23
+ * Build an absolute docs URL for a content slug (the MDX stem under
24
+ * `packages/core/docs/content/`).
25
+ *
26
+ * `getting-started` maps to `/docs` (the docs home).
27
+ */
28
+ export function docsUrl(slug, options = {}) {
29
+ const normalized = slug.replace(/^\/+/, "").replace(/\/+$/, "");
30
+ const path = normalized === "" || normalized === "getting-started"
31
+ ? "/docs"
32
+ : `/docs/${normalized}`;
33
+ const url = new URL(path, AGENT_NATIVE_DOCS_ORIGIN);
34
+ applyDocsUtm(url.searchParams, options);
35
+ if (options.hash) {
36
+ url.hash = options.hash.replace(/^#/, "");
37
+ }
38
+ return url.toString();
39
+ }
@@ -6,6 +6,7 @@ export { truncate } from "./truncate.js";
6
6
  export { isHumanReadableDocumentTitle, normalizeDocumentTitle, } from "./document-title.js";
7
7
  export { injectDocumentMarkup } from "./html-document.js";
8
8
  export { withBuilderUtmTrackingParams } from "./builder-link-tracking.js";
9
+ export { AGENT_NATIVE_DOCS_ORIGIN, docsUrl, type DocsUrlOptions, } from "./docs-url.js";
9
10
  export { buildRuntimeConfigPrompt, formatRuntimeConfigReport, getRuntimeConfigReport, parseRuntimeConfigReport, runtimeConfigRequirementsFromSearchParams, type RuntimeConfigEnvironment, type RuntimeConfigIssue, type RuntimeConfigIssueCode, type RuntimeConfigIssueSeverity, type RuntimeConfigPhase, type RuntimeConfigReport, type RuntimeConfigRequirements, } from "./runtime-config.js";
10
11
  export { llmConnectionTrackingProperties, normalizeLlmConnection, type LlmConnectionStatus, } from "./llm-connection.js";
11
12
  export { DISPATCH_WORKSPACE_ROOT_REDIRECTS, RESERVED_WORKSPACE_APP_IDS, assertValidWorkspaceAppId, getWorkspaceAppIdValidationError, isValidWorkspaceAppIdFormat, normalizeWorkspaceAppId, } from "./workspace-app-id.js";
@@ -6,6 +6,7 @@ export { truncate } from "./truncate.js";
6
6
  export { isHumanReadableDocumentTitle, normalizeDocumentTitle, } from "./document-title.js";
7
7
  export { injectDocumentMarkup } from "./html-document.js";
8
8
  export { withBuilderUtmTrackingParams } from "./builder-link-tracking.js";
9
+ export { AGENT_NATIVE_DOCS_ORIGIN, docsUrl, } from "./docs-url.js";
9
10
  export { buildRuntimeConfigPrompt, formatRuntimeConfigReport, getRuntimeConfigReport, parseRuntimeConfigReport, runtimeConfigRequirementsFromSearchParams, } from "./runtime-config.js";
10
11
  export { llmConnectionTrackingProperties, normalizeLlmConnection, } from "./llm-connection.js";
11
12
  export { DISPATCH_WORKSPACE_ROOT_REDIRECTS, RESERVED_WORKSPACE_APP_IDS, assertValidWorkspaceAppId, getWorkspaceAppIdValidationError, isValidWorkspaceAppIdFormat, normalizeWorkspaceAppId, } from "./workspace-app-id.js";
@@ -1,5 +1,6 @@
1
1
  import { useActionQuery } from "@agent-native/core/client/hooks";
2
2
  import { useT } from "@agent-native/core/client/i18n";
3
+ import { docsUrl } from "@agent-native/core/shared";
3
4
  import { useTheme } from "next-themes";
4
5
  import { Link } from "react-router";
5
6
 
@@ -41,7 +42,7 @@ export default function IndexPage() {
41
42
 
42
43
  <div className="grid grid-cols-2 gap-3 text-left">
43
44
  <a
44
- href="https://agent-native.com/docs"
45
+ href={docsUrl("getting-started")}
45
46
  target="_blank"
46
47
  rel="noopener noreferrer"
47
48
  className="group rounded-lg border border-border/50 px-4 py-3 hover:bg-accent/50 transition-colors"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.153.9",
3
+ "version": "0.153.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": {
@@ -421,8 +421,8 @@
421
421
  "y-protocols": "^1.0.7",
422
422
  "yjs": "^13.6.31",
423
423
  "zod": "^4.3.6",
424
- "@agent-native/recap-cli": "0.5.4",
425
- "@agent-native/toolkit": "^0.14.1"
424
+ "@agent-native/toolkit": "^0.14.1",
425
+ "@agent-native/recap-cli": "0.5.4"
426
426
  },
427
427
  "devDependencies": {
428
428
  "@ai-sdk/anthropic": "^3.0.71",
@@ -1,5 +1,6 @@
1
1
  import { useActionQuery } from "@agent-native/core/client/hooks";
2
2
  import { useT } from "@agent-native/core/client/i18n";
3
+ import { docsUrl } from "@agent-native/core/shared";
3
4
  import { useTheme } from "next-themes";
4
5
  import { Link } from "react-router";
5
6
 
@@ -41,7 +42,7 @@ export default function IndexPage() {
41
42
 
42
43
  <div className="grid grid-cols-2 gap-3 text-left">
43
44
  <a
44
- href="https://agent-native.com/docs"
45
+ href={docsUrl("getting-started")}
45
46
  target="_blank"
46
47
  rel="noopener noreferrer"
47
48
  className="group rounded-lg border border-border/50 px-4 py-3 hover:bg-accent/50 transition-colors"