@agent-native/core 0.137.3 → 0.137.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/analytics/actions/gong-calls.ts +37 -17
- package/corpus/templates/analytics/app/lib/data-sources.ts +1 -1
- package/corpus/templates/analytics/server/lib/gong.ts +51 -2
- package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/brain/app/routes/settings.tsx +1 -1
- package/corpus/templates/brain/server/register-secrets.ts +1 -1
- package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/chat/AGENTS.md +11 -0
- package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/chat/app/root.tsx +1 -1
- package/corpus/templates/chat/app/routes/agent.tsx +29 -13
- package/corpus/templates/chat/vite.config.ts +42 -0
- package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/clips/app/components/library/empty-state.tsx +1 -3
- package/corpus/templates/clips/app/components/library/library-grid.tsx +2 -6
- package/corpus/templates/clips/app/components/library/library-layout.tsx +2 -6
- package/corpus/templates/clips/app/components/recorder/pre-record-panel.tsx +1 -3
- package/corpus/templates/clips/app/routes/bug-report.tsx +1 -8
- package/corpus/templates/clips/app/routes/import.tsx +1 -3
- package/corpus/templates/clips/changelog/2026-08-04-recording-buttons-are-now-text-only-for-a-cleaner-clips-inte.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-04-save-settings-now-matches-the-other-clips-settings-buttons.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-04-signing-out-now-takes-effect-immediately-after-verifying-a-n.md +6 -0
- package/corpus/templates/clips/chrome-extension/src/styles.css +1 -0
- package/corpus/templates/clips/desktop/src/app.tsx +1 -1
- package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/crm/app/routes/settings.tsx +2 -2
- package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/design/actions/import-figma-clipboard.ts +1 -1
- package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/dispatch/changelog/2026-08-04-dispatch-keeps-connected-chats-out-of-local-history-by-defau.md +6 -0
- package/corpus/templates/factory/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/factory/README.md +1 -1
- package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +0 -2
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +1 -1
- package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +53 -1
- package/corpus/templates/slides/actions/generate-image-api.ts +15 -4
- package/corpus/templates/slides/actions/import-google-slides-reference.ts +83 -0
- package/corpus/templates/slides/actions/import-pptx.ts +134 -117
- package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +387 -0
- package/corpus/templates/slides/app/components/editor/ImageGenPanel.tsx +78 -48
- package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +377 -187
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +0 -1
- package/corpus/templates/slides/app/hooks/use-deck-design-system.ts +20 -1
- package/corpus/templates/slides/app/i18n/en-US.ts +15 -0
- package/corpus/templates/slides/app/lib/new-deck-reference-selection.ts +22 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +4 -1
- package/corpus/templates/slides/app/pages/Index.tsx +172 -85
- package/corpus/templates/slides/server/lib/assets-image-delegation.ts +4 -2
- package/corpus/templates/slides/shared/api.ts +14 -1
- package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +53 -1
- package/dist/chat-threads/schema.d.ts +57 -0
- package/dist/chat-threads/schema.js +3 -0
- package/dist/chat-threads/store.d.ts +26 -0
- package/dist/chat-threads/store.js +84 -6
- package/dist/client/AgentPanel.js +11 -5
- package/dist/client/ConnectBuilderCard.js +1 -1
- package/dist/client/agent-page/AgentEmptyState.d.ts +2 -1
- package/dist/client/agent-page/AgentEmptyState.js +6 -2
- package/dist/client/agent-page/AgentJobsTab.d.ts +3 -1
- package/dist/client/agent-page/AgentJobsTab.js +55 -44
- package/dist/client/agent-page/AgentTabFrame.d.ts +2 -1
- package/dist/client/agent-page/AgentTabFrame.js +4 -2
- package/dist/client/agent-page/AgentTabsPage.js +12 -8
- package/dist/client/agent-page/AgentWorkspaceContent.d.ts +10 -0
- package/dist/client/agent-page/AgentWorkspaceContent.js +110 -0
- package/dist/client/agent-page/AutomationDetailsDialog.js +1 -1
- package/dist/client/chat/run-recovery.js +3 -3
- package/dist/client/error-format.js +1 -1
- package/dist/client/integrations/IntegrationsPanel.d.ts +1 -0
- package/dist/client/integrations/IntegrationsPanel.js +149 -5
- package/dist/client/onboarding/FirstRunOnboarding.js +130 -15
- package/dist/client/onboarding/index.d.ts +1 -1
- package/dist/client/onboarding/index.js +1 -1
- package/dist/client/onboarding/use-onboarding.js +12 -2
- package/dist/client/onboarding/use-preview-mode.d.ts +4 -0
- package/dist/client/onboarding/use-preview-mode.js +9 -0
- package/dist/client/resources/BuiltinCapabilityDetail.js +2 -2
- package/dist/client/resources/ResourceTree.d.ts +4 -1
- package/dist/client/resources/ResourceTree.js +13 -8
- package/dist/client/resources/ResourcesPanel.js +7 -3
- package/dist/client/resources/mcp-integration-catalog.js +4 -4
- package/dist/client/resources/use-mcp-servers.js +6 -6
- package/dist/client/settings/AgentsSection.js +15 -16
- package/dist/client/settings/AutomationsSection.js +1 -1
- package/dist/client/settings/DemoModeSection.js +1 -1
- package/dist/client/settings/SettingsPanel.d.ts +3 -1
- package/dist/client/settings/SettingsPanel.js +284 -88
- package/dist/client/settings/SettingsRow.js +1 -1
- package/dist/client/settings/SettingsSection.d.ts +6 -4
- package/dist/client/settings/SettingsSection.js +6 -6
- package/dist/client/settings/SettingsTabsPage.js +47 -25
- package/dist/client/settings/VoiceTranscriptionSection.d.ts +3 -1
- package/dist/client/settings/VoiceTranscriptionSection.js +20 -8
- package/dist/client/settings/agent-settings-search.d.ts +1 -1
- package/dist/client/settings/agent-settings-search.js +8 -8
- package/dist/client/transcription/BuilderTranscriptionCta.js +2 -2
- package/dist/client/use-chat-threads.d.ts +9 -0
- package/dist/client/use-chat-threads.js +22 -6
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/integrations/google-docs-poller.js +9 -1
- package/dist/integrations/webhook-handler.js +11 -1
- package/dist/jobs/scheduler.d.ts +4 -1
- package/dist/jobs/scheduler.js +34 -9
- package/dist/localization/default-messages.js +40 -40
- package/dist/mcp-client/oauth-routes.js +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
- package/dist/provider-api/actions/provider-api.d.ts +15 -15
- package/dist/secrets/onboarding.js +1 -1
- package/dist/server/agent-chat/browser-team-tools.d.ts +1 -0
- package/dist/server/agent-chat/browser-team-tools.js +1 -0
- package/dist/server/agent-chat-plugin.js +14 -1
- package/dist/server/agent-teams.d.ts +2 -0
- package/dist/server/agent-teams.js +2 -0
- package/dist/server/auth.js +35 -13
- package/dist/server/better-auth-instance.d.ts +1 -0
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/workspace-provider-oauth.js +1 -1
- package/dist/setup-connections/onboarding.js +2 -2
- package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
- package/dist/templates/chat/AGENTS.md +11 -0
- package/dist/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/dist/templates/chat/app/root.tsx +1 -1
- package/dist/templates/chat/app/routes/agent.tsx +29 -13
- package/dist/templates/chat/vite.config.ts +42 -0
- package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +53 -1
- package/dist/templates/default/AGENTS.md +11 -0
- package/dist/templates/default/vite.config.ts +42 -0
- package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +53 -1
- package/dist/templates/workspace-core/AGENTS.md +11 -0
- package/dist/templates/workspace-root/AGENTS.md +14 -0
- package/dist/vite/client.js +56 -0
- package/package.json +2 -2
- package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +53 -1
- package/src/templates/chat/AGENTS.md +11 -0
- package/src/templates/chat/app/components/layout/Layout.tsx +1 -1
- package/src/templates/chat/app/root.tsx +1 -1
- package/src/templates/chat/app/routes/agent.tsx +29 -13
- package/src/templates/chat/vite.config.ts +42 -0
- package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +53 -1
- package/src/templates/default/AGENTS.md +11 -0
- package/src/templates/default/vite.config.ts +42 -0
- package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +33 -0
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +53 -1
- package/src/templates/workspace-core/AGENTS.md +11 -0
- package/src/templates/workspace-root/AGENTS.md +14 -0
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Checkbox, Picker, TextField, } from "@agent-native/toolkit/design-system";
|
|
3
3
|
import { Button as ToolkitButton } from "@agent-native/toolkit/ui/button";
|
|
4
|
-
import {
|
|
4
|
+
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, } from "@agent-native/toolkit/ui/command";
|
|
5
|
+
import { IconChevronDown, IconChevronRight, IconCheck, IconExternalLink, IconBrain, IconHierarchy2, IconBrowser, IconGitBranch, IconCloud, IconDatabase, IconFolder, IconShield, IconShieldLock, IconPlugConnected, IconTopologyRing2, IconLoader2, IconUpload, IconCoin, IconMail, IconKey, IconMicrophone, IconEyeOff, IconBolt, IconGauge, IconApps, IconUsersGroup, IconTool, } from "@tabler/icons-react";
|
|
5
6
|
import React, { Suspense, lazy, useState, useEffect, useCallback, useMemo, useRef, } from "react";
|
|
6
|
-
import { Link, Navigate } from "react-router";
|
|
7
7
|
import { PROVIDER_ENV_PLACEHOLDERS } from "../../agent/engine/provider-env-vars.js";
|
|
8
8
|
import { saveAgentEngineProviderSettings } from "../agent-engine-key.js";
|
|
9
|
+
import { AgentWorkspaceContent } from "../agent-page/AgentWorkspaceContent.js";
|
|
9
10
|
import { agentNativePath } from "../api-path.js";
|
|
10
11
|
import { BuilderBMark } from "../builder-mark.js";
|
|
12
|
+
import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
|
|
11
13
|
import { Tooltip, TooltipContent, TooltipTrigger, } from "../components/ui/tooltip.js";
|
|
12
14
|
import { useT } from "../i18n.js";
|
|
13
15
|
import { TeamPage } from "../org/TeamPage.js";
|
|
@@ -15,12 +17,13 @@ import { BuilderConnectCard } from "../setup-connections/BuilderConnectCard.js";
|
|
|
15
17
|
import { callAction } from "../use-action.js";
|
|
16
18
|
import { useDevMode } from "../use-dev-mode.js";
|
|
17
19
|
import { cn } from "../utils.js";
|
|
18
|
-
import { AGENT_SETTINGS_SECTIONS, ALL_SETTINGS_SECTIONS,
|
|
20
|
+
import { AGENT_SETTINGS_SECTIONS, ALL_SETTINGS_SECTIONS, INTEGRATION_SETTINGS_SECTIONS, WORKSPACE_SETTINGS_SECTIONS, getAgentSettingsSearchTabs, } from "./agent-settings-search.js";
|
|
19
21
|
import { AgentsSection } from "./AgentsSection.js";
|
|
20
22
|
import { AutomationsSection } from "./AutomationsSection.js";
|
|
21
23
|
import { DemoModeSection } from "./DemoModeSection.js";
|
|
22
24
|
import { ExtensionsSettingsContent } from "./ExtensionsSettingsContent.js";
|
|
23
25
|
import { SecretsSection } from "./SecretsSection.js";
|
|
26
|
+
import { SettingsGroup, SettingsRow } from "./SettingsRow.js";
|
|
24
27
|
import { SettingsSection, SettingsSurfaceProvider, useSettingsSurface, } from "./SettingsSection.js";
|
|
25
28
|
import { UsageSection } from "./UsageSection.js";
|
|
26
29
|
import { useBuilderConnectFlow, useBuilderStatus, } from "./useBuilderStatus.js";
|
|
@@ -28,6 +31,8 @@ import { settingsSectionDomId, useSettingsPanelController, } from "./useSettings
|
|
|
28
31
|
import { VoiceTranscriptionSection } from "./VoiceTranscriptionSection.js";
|
|
29
32
|
const Button = React.forwardRef(({ className, ...props }, ref) => (_jsx(ToolkitButton, { ref: ref, variant: "ghost", className: cn("h-auto p-0 hover:bg-transparent hover:text-inherit active:scale-100 [&_svg]:!size-auto", className), ...props })));
|
|
30
33
|
Button.displayName = "SettingsPrimitiveButton";
|
|
34
|
+
const ManageButton = React.forwardRef(({ children = "Manage", className, ...props }, ref) => (_jsxs(Button, { ref: ref, type: "button", intent: "neutral", emphasis: "outline", className: cn("inline-flex items-center gap-1 rounded-md border border-border px-3 py-1.5 text-sm font-medium text-foreground hover:bg-accent/40", className), ...props, children: [children, _jsx(IconChevronDown, { size: 14 })] })));
|
|
35
|
+
ManageButton.displayName = "SettingsManageButton";
|
|
31
36
|
const IntegrationsPanel = lazy(() => import("../integrations/IntegrationsPanel.js").then((m) => ({
|
|
32
37
|
default: m.IntegrationsPanel,
|
|
33
38
|
})));
|
|
@@ -182,32 +187,43 @@ function DisconnectBuilderButton() {
|
|
|
182
187
|
return (_jsxs(_Fragment, { children: [_jsx(Button, { type: "button", intent: "danger", emphasis: "outline", onClick: handleDisconnectClick, disabled: phase === "busy", className: "inline-flex items-center gap-1 rounded border border-border px-2 py-0.5 text-[10px] text-muted-foreground hover:text-foreground hover:bg-accent/40 disabled:opacity-60 disabled:cursor-wait", "aria-busy": phase === "busy", children: phase === "busy" ? (_jsxs(_Fragment, { children: [_jsx(IconLoader2, { size: 10, className: "animate-spin" }), "Disconnecting\u2026"] })) : ("Disconnect") }), err && _jsx("span", { className: "text-[10px] text-destructive", children: err })] }));
|
|
183
188
|
}
|
|
184
189
|
// ─── "Connect Builder.io" card (shared across all sections) ─────────────────
|
|
185
|
-
function UseBuilderCard({ builderFlow, connectUrl, connected, orgName, envManaged, credentialSource, trackingSource = "settings_panel_builder_card", trackingFlow = "connect_llm", label = "Connect Builder.io", subtitle = "
|
|
190
|
+
function UseBuilderCard({ builderFlow, connectUrl, connected, orgName, envManaged, credentialSource, trackingSource = "settings_panel_builder_card", trackingFlow = "connect_llm", label = "Connect Builder.io", subtitle = "Builder.io free credits to start - no API key needed.", dim, compact = false, }) {
|
|
186
191
|
const isPage = useSettingsSurface() === "page";
|
|
187
192
|
const effectiveConnected = connected || builderFlow.configured;
|
|
188
193
|
const effectiveOrgName = builderFlow.orgName ?? orgName;
|
|
189
194
|
const bgClass = dim ? "" : "bg-accent/30";
|
|
190
195
|
const titleCls = isPage ? "text-sm" : "text-[11px]";
|
|
191
196
|
const bodyCls = isPage ? "text-xs" : "text-[10px]";
|
|
197
|
+
if (compact && effectiveConnected) {
|
|
198
|
+
return (_jsxs("span", { className: "inline-flex shrink-0 items-center gap-1 text-sm text-primary", children: [_jsx(IconCheck, { size: 14 }), "Connected", effectiveOrgName ? ` · ${effectiveOrgName}` : ""] }));
|
|
199
|
+
}
|
|
192
200
|
if (effectiveConnected) {
|
|
193
201
|
return (_jsxs("div", { className: cn("rounded-md border border-border", isPage ? "px-3.5 py-3" : "px-2.5 py-2", bgClass), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("div", { className: cn("font-medium text-foreground", titleCls), children: "Builder.io" }), _jsxs("span", { className: cn("flex items-center gap-1 text-green-500", bodyCls), children: [_jsx(IconCheck, { size: isPage ? 14 : 10 }), "Connected"] })] }), effectiveOrgName && (_jsx("p", { className: cn("text-muted-foreground mt-0.5", bodyCls), children: effectiveOrgName })), envManaged ? (_jsx("p", { className: cn("text-muted-foreground mt-1", bodyCls), children: credentialSource === "env"
|
|
194
202
|
? "Deployment fallback is available. Connect your own account to override it."
|
|
195
|
-
: "Using your connected Builder account. Deployment fallback is still available." })) : null, connectUrl || credentialSource !== "env" ? (_jsxs("div", { className: "flex items-center gap-2 mt-2.5", children: [connectUrl && (
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
203
|
+
: "Using your connected Builder account. Deployment fallback is still available." })) : null, connectUrl || credentialSource !== "env" ? (_jsxs("div", { className: "flex items-center gap-2 mt-2.5", children: [connectUrl && (_jsx(Button, { type: "button", intent: "neutral", emphasis: "ghost", onClick: () => builderFlow.start({ trackingSource, trackingFlow }), disabled: builderFlow.connecting, className: cn(pillButtonClass(isPage, "ghost"), "no-underline"), children: builderFlow.connecting
|
|
204
|
+
? "Connecting..."
|
|
205
|
+
: credentialSource === "env"
|
|
206
|
+
? "Connect account"
|
|
207
|
+
: "Reconnect" })), credentialSource !== "env" ? _jsx(DisconnectBuilderButton, {}) : null] })) : null] }));
|
|
200
208
|
}
|
|
201
209
|
if (!connectUrl)
|
|
202
210
|
return null;
|
|
203
|
-
|
|
211
|
+
if (compact) {
|
|
212
|
+
return (_jsxs(Button, { type: "button", intent: "primary", emphasis: "solid", onClick: () => builderFlow.start({ trackingSource, trackingFlow }), disabled: builderFlow.connecting, className: "inline-flex shrink-0 items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:cursor-wait disabled:opacity-70", children: [builderFlow.connecting ? "Connecting…" : "Connect Builder.io", builderFlow.connecting ? (_jsx(IconLoader2, { size: 14, className: "animate-spin" })) : null] }));
|
|
213
|
+
}
|
|
214
|
+
return (_jsxs("div", { className: cn("flex w-full items-center gap-3 rounded-xl border border-border/70 bg-card text-start transition-colors", isPage ? "px-4 py-3.5" : "px-3 py-3", builderFlow.error && "border-destructive/40"), children: [_jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: [_jsx("div", { className: cn("flex shrink-0 items-center justify-center rounded-md bg-foreground text-background", isPage ? "h-8 w-8" : "h-7 w-7"), children: _jsx(BuilderBMark, { className: isPage ? "h-4 w-4" : "h-3.5 w-3.5" }) }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs("div", { className: "flex items-center gap-1.5 flex-wrap", children: [_jsx("span", { className: cn("font-semibold text-foreground", isPage ? "text-sm" : "text-[12px]"), children: builderFlow.connecting ? "Connecting Builder.io..." : label }), builderFlow.connecting && (_jsx(IconLoader2, { size: isPage ? 14 : 12, className: "shrink-0 animate-spin text-muted-foreground" }))] }), _jsx("p", { className: cn("text-muted-foreground mt-0.5 leading-snug", isPage ? "text-xs" : "text-[10.5px]"), children: subtitle }), builderFlow.error && (_jsx("p", { className: cn("mt-1 text-destructive", bodyCls), children: builderFlow.error }))] })] }), _jsxs(Button, { type: "button", intent: "neutral", emphasis: "outline", onClick: () => builderFlow.start({ trackingSource, trackingFlow }), disabled: builderFlow.connecting, className: cn("inline-flex shrink-0 items-center gap-1.5 rounded-md border border-border px-3 py-1.5 font-medium text-foreground hover:bg-accent/40 disabled:cursor-wait disabled:opacity-70", isPage ? "text-sm" : "text-[11px]"), children: [builderFlow.connecting ? "Connecting…" : "Connect Builder.io", builderFlow.connecting ? (_jsx(IconLoader2, { size: isPage ? 14 : 12, className: "animate-spin" })) : null] })] }));
|
|
204
215
|
}
|
|
205
216
|
// ─── Manual setup card ──────────────────────────────────────────────────────
|
|
206
|
-
function ManualSetupCard({ id, hint, docsUrl, docsLabel = "Read the docs", children, dim, sourceBadge, }) {
|
|
217
|
+
function ManualSetupCard({ id, title = "Set up manually", hint, docsUrl, docsLabel = "Read the docs", children, dim, sourceBadge, bare = false, popover = false, popoverLabel = "Manage", }) {
|
|
207
218
|
const isPage = useSettingsSurface() === "page";
|
|
208
219
|
const titleCls = isPage ? "text-sm" : "text-[11px]";
|
|
209
220
|
const bodyCls = isPage ? "text-xs" : "text-[10px]";
|
|
210
|
-
|
|
221
|
+
const content = (_jsxs("div", { id: id, className: cn(bare
|
|
222
|
+
? "space-y-2"
|
|
223
|
+
: cn("rounded-md border border-border", isPage ? "px-3.5 py-3" : "px-2.5 py-2", dim ? "" : "bg-accent/30")), children: [_jsxs("div", { className: "flex items-center justify-between mb-1", children: [_jsx("div", { className: cn("font-medium text-foreground", titleCls), children: title }), sourceBadge ? (_jsxs("span", { className: cn("flex items-center gap-1 text-green-500", bodyCls), children: [_jsx(IconCheck, { size: isPage ? 14 : 10 }), sourceBadge] })) : null] }), hint && (_jsx("p", { className: cn("text-muted-foreground mb-1.5", bodyCls), children: hint })), children, docsUrl && (_jsxs("a", { href: docsUrl, target: "_blank", rel: "noopener noreferrer", className: cn(pillButtonClass(isPage, "outline"), "mt-1.5 no-underline"), children: [docsLabel, _jsx(IconExternalLink, { size: isPage ? 14 : 10 })] }))] }));
|
|
224
|
+
if (!popover)
|
|
225
|
+
return content;
|
|
226
|
+
return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(ManageButton, { children: popoverLabel }) }), _jsx(PopoverContent, { align: "end", sideOffset: 6, className: "max-h-[min(640px,calc(100vh-2rem))] w-[min(420px,calc(100vw-2rem))] overflow-y-auto p-4", children: content })] }));
|
|
211
227
|
}
|
|
212
228
|
// ─── LLM helpers ────────────────────────────────────────────────────────────
|
|
213
229
|
function friendlyModelName(model) {
|
|
@@ -312,7 +328,7 @@ const PROVIDER_DOCS = {
|
|
|
312
328
|
"ai-sdk:mistral": "https://console.mistral.ai/api-keys/",
|
|
313
329
|
"ai-sdk:cohere": "https://dashboard.cohere.com/api-keys",
|
|
314
330
|
};
|
|
315
|
-
function LLMSectionInner({ builderFlow, builderLoading, connectUrl, connected, orgName, envManaged, credentialSource, open, onToggle, }) {
|
|
331
|
+
function LLMSectionInner({ builderFlow, builderLoading, connectUrl, connected, orgName, envManaged, credentialSource, grouped = false, open, onToggle, }) {
|
|
316
332
|
const isPage = useSettingsSurface() === "page";
|
|
317
333
|
const t = useT();
|
|
318
334
|
const [envKeys, setEnvKeys] = useState([]);
|
|
@@ -533,33 +549,35 @@ function LLMSectionInner({ builderFlow, builderLoading, connectUrl, connected, o
|
|
|
533
549
|
}
|
|
534
550
|
catch { }
|
|
535
551
|
};
|
|
536
|
-
return (_jsx(SettingsSection, { id: settingsSectionDomId("llm"), icon: _jsx(IconBrain, { size: 14 }), title: "LLM", subtitle: "
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
552
|
+
return (_jsx(SettingsSection, { id: settingsSectionDomId("llm"), icon: _jsx(IconBrain, { size: 14 }), title: "LLM", subtitle: "Use Builder.io free credits or your own LLM provider.", required: true, connected: initialLoading ? undefined : anyKeyConfigured, grouped: isPage && grouped, open: open, onToggle: onToggle, children: initialLoading ? (_jsx("div", { className: cn(isPage && "px-5 py-4 sm:px-6"), children: _jsx(SettingsSkeleton, { lines: 3 }) })) : (_jsxs("div", { className: cn(isPage
|
|
553
|
+
? "flex items-center justify-between gap-4 px-5 py-4 sm:px-6"
|
|
554
|
+
: "space-y-2"), children: [isPage && (_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-sm font-medium text-foreground", children: "Connect an LLM" }), _jsx("p", { className: "mt-1 text-sm leading-6 text-muted-foreground", children: "Use Builder.io free credits or your own provider." })] })), _jsxs("div", { className: cn(isPage && "flex flex-wrap items-center justify-end gap-2"), children: [_jsx(UseBuilderCard, { builderFlow: builderFlow, connectUrl: connectUrl, connected: connected, orgName: orgName, envManaged: envManaged, credentialSource: credentialSource, trackingSource: "llm_settings", trackingFlow: "connect_llm", label: "Connect Builder.io", compact: isPage }), builderConnected && !isPage && (_jsxs(Button, { type: "button", intent: "neutral", emphasis: "ghost", "aria-expanded": manualSetupOpen, "aria-controls": "llm-manual-setup", onClick: () => setManualSetupOpen((open) => !open), className: cn("inline-flex items-center gap-1 px-0.5 text-muted-foreground hover:text-foreground", isPage ? "text-xs" : "text-[10px]"), children: [t("agentPanel.addOwnKeys", {
|
|
555
|
+
defaultValue: "Add your own keys",
|
|
556
|
+
}), _jsx(IconChevronDown, { size: isPage ? 14 : 11, className: cn("transition-transform", manualSetupOpen && "rotate-180") })] })), (!builderConnected || manualSetupOpen || isPage) && (_jsx(ManualSetupCard, { id: "llm-manual-setup", title: "Custom keys", hint: manualSetupHint, sourceBadge: builderConnected ? undefined : sourceBadge, bare: isPage, popover: isPage, popoverLabel: "Custom keys", children: _jsxs("div", { className: "space-y-2 mb-1", children: [_jsx(SettingsSelect, { label: "Provider", value: selectedEngine, options: providerOptions, onValueChange: (val) => {
|
|
557
|
+
setSelectedEngine(val);
|
|
558
|
+
const info = engines.find((e) => e.name === val);
|
|
559
|
+
setSelectedModel(info?.defaultModel ?? "");
|
|
560
|
+
setApiKey("");
|
|
561
|
+
setBaseUrl("");
|
|
562
|
+
setClearBaseUrl(false);
|
|
563
|
+
setAdvancedOpen(false);
|
|
564
|
+
} }), _jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: fieldLabelClass(isPage), children: "Model" }), _jsx("input", { type: "text", list: `model-suggestions-${selectedEngine}`, value: selectedModel, onChange: (e) => setSelectedModel(e.target.value), placeholder: selectedEngineInfo?.defaultModel ?? "e.g. model-id", spellCheck: false, autoComplete: "off", className: textInputClass(isPage), style: isPage ? CONTROL_STYLE_PAGE : CONTROL_STYLE }), modelOptions.length > 0 && (_jsx("datalist", { id: `model-suggestions-${selectedEngine}`, children: modelOptions.map((opt) => (_jsx("option", { value: opt.value, label: opt.label }, opt.value))) }))] }), isOpenAiEngine && (_jsxs("div", { className: "border-t border-border/70 pt-2", children: [_jsxs(Button, { type: "button", onClick: () => setAdvancedOpen((v) => !v), className: "flex w-full cursor-pointer items-center justify-between gap-2 rounded px-0.5 py-1 text-left hover:text-foreground", children: [_jsxs("span", { className: "inline-flex min-w-0 items-center gap-1.5 text-[11px] font-medium text-foreground", children: [advancedOpen ? (_jsx(IconChevronDown, { size: 12 })) : (_jsx(IconChevronRight, { size: 12, className: "rtl:-scale-x-100" })), "Advanced"] }), _jsx("span", { className: "truncate text-[10px] text-muted-foreground", children: "OpenAI-compatible endpoint" })] }), advancedOpen && (_jsxs("div", { className: "mt-1.5 space-y-1.5", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("p", { className: "text-[12px] font-medium text-foreground", children: "Endpoint URL" }), _jsx("span", { className: "text-[10px] text-muted-foreground", children: baseUrlConfigured ? "Configured" : "Optional" })] }), _jsx("input", { type: "url", value: baseUrl, onChange: (e) => {
|
|
565
|
+
setBaseUrl(e.target.value);
|
|
566
|
+
if (e.target.value.trim())
|
|
567
|
+
setClearBaseUrl(false);
|
|
568
|
+
}, onKeyDown: (e) => {
|
|
569
|
+
if (e.key === "Enter")
|
|
570
|
+
handleSave();
|
|
571
|
+
}, placeholder: baseUrlConfigured
|
|
572
|
+
? "Leave blank to keep current endpoint"
|
|
573
|
+
: "https://gateway.example/v1", disabled: clearBaseUrl, spellCheck: false, autoComplete: "off", className: "flex h-9 w-full rounded-md border border-border bg-background px-3 text-[12px] text-foreground outline-none transition-colors hover:bg-accent/40 focus:ring-1 focus:ring-accent disabled:opacity-50 placeholder:text-muted-foreground/50", style: CONTROL_STYLE }), _jsx("p", { className: "text-[10px] leading-relaxed text-muted-foreground", children: "Use for LiteLLM or another OpenAI-compatible chat gateway. Leave blank for OpenAI." }), baseUrlConfigured && (_jsxs("label", { className: "flex items-center gap-1.5 text-[10px] text-muted-foreground", children: [_jsx(Checkbox, { checked: clearBaseUrl, onChange: (checked) => {
|
|
574
|
+
setClearBaseUrl(checked);
|
|
575
|
+
if (checked)
|
|
576
|
+
setBaseUrl("");
|
|
577
|
+
}, "aria-label": "Clear saved endpoint override", className: "shrink-0" }), "Clear saved endpoint override"] })), envVar && envConfigured && endpointChanged && (_jsx(Button, { type: "button", intent: "neutral", emphasis: "solid", onClick: handleSave, disabled: saving, className: "rounded bg-accent px-2.5 py-1 text-[10px] font-medium text-foreground hover:bg-accent/80 disabled:opacity-40", children: saving ? (_jsx(IconLoader2, { size: 10, className: "animate-spin" })) : saved ? (_jsx(IconCheck, { size: 10 })) : ("Save endpoint") }))] }))] })), envVar && envConfigured ? (_jsxs("div", { className: cn("flex items-center gap-1.5 text-primary", isPage ? "text-xs" : "text-[10px]"), children: [_jsx(IconCheck, { size: isPage ? 14 : 10 }), envVar, " configured"] })) : envVar ? (_jsxs("div", { className: "flex gap-1.5", children: [_jsx("input", { type: "password", value: apiKey, onChange: (e) => setApiKey(e.target.value), onKeyDown: (e) => {
|
|
551
578
|
if (e.key === "Enter")
|
|
552
579
|
handleSave();
|
|
553
|
-
}, placeholder:
|
|
554
|
-
? "Leave blank to keep current endpoint"
|
|
555
|
-
: "https://gateway.example/v1", disabled: clearBaseUrl, spellCheck: false, autoComplete: "off", className: "flex h-9 w-full rounded-md border border-border bg-background px-3 text-[12px] text-foreground outline-none transition-colors hover:bg-accent/40 focus:ring-1 focus:ring-accent disabled:opacity-50 placeholder:text-muted-foreground/50", style: CONTROL_STYLE }), _jsx("p", { className: "text-[10px] leading-relaxed text-muted-foreground", children: "Use for LiteLLM or another OpenAI-compatible chat gateway. Leave blank for OpenAI." }), baseUrlConfigured && (_jsxs("label", { className: "flex items-center gap-1.5 text-[10px] text-muted-foreground", children: [_jsx(Checkbox, { checked: clearBaseUrl, onChange: (checked) => {
|
|
556
|
-
setClearBaseUrl(checked);
|
|
557
|
-
if (checked)
|
|
558
|
-
setBaseUrl("");
|
|
559
|
-
}, "aria-label": "Clear saved endpoint override", className: "shrink-0" }), "Clear saved endpoint override"] })), envVar && envConfigured && endpointChanged && (_jsx(Button, { type: "button", intent: "neutral", emphasis: "solid", onClick: handleSave, disabled: saving, className: "rounded bg-accent px-2.5 py-1 text-[10px] font-medium text-foreground hover:bg-accent/80 disabled:opacity-40", children: saving ? (_jsx(IconLoader2, { size: 10, className: "animate-spin" })) : saved ? (_jsx(IconCheck, { size: 10 })) : ("Save endpoint") }))] }))] })), envVar && envConfigured ? (_jsxs("div", { className: cn("flex items-center gap-1.5 text-green-500", isPage ? "text-xs" : "text-[10px]"), children: [_jsx(IconCheck, { size: isPage ? 14 : 10 }), envVar, " configured"] })) : envVar ? (_jsxs("div", { className: "flex gap-1.5", children: [_jsx("input", { type: "password", value: apiKey, onChange: (e) => setApiKey(e.target.value), onKeyDown: (e) => {
|
|
560
|
-
if (e.key === "Enter")
|
|
561
|
-
handleSave();
|
|
562
|
-
}, placeholder: PROVIDER_ENV_PLACEHOLDERS[envVar] ?? "...", className: cn(textInputClass(isPage), "flex-1"), style: isPage ? CONTROL_STYLE_PAGE : undefined }), _jsx(Button, { intent: "primary", emphasis: "solid", onClick: handleSave, disabled: !providerSettingsChanged || saving, className: pillButtonClass(isPage, "solid"), children: saving ? (_jsx(IconLoader2, { size: isPage ? 14 : 10, className: "animate-spin" })) : saved ? (_jsx(IconCheck, { size: isPage ? 14 : 10 })) : ("Save") })] })) : null, _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { intent: "neutral", emphasis: "outline", onClick: handleTest, disabled: testing, className: pillButtonClass(isPage, "outline"), children: testing ? (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(IconLoader2, { size: isPage ? 14 : 10, className: "animate-spin" }), "Testing\u2026"] })) : ("Test") }), PROVIDER_DOCS[selectedEngine] ? (_jsxs("a", { href: PROVIDER_DOCS[selectedEngine], target: "_blank", rel: "noopener noreferrer", className: cn(pillButtonClass(isPage, "outline"), "no-underline"), children: ["Get an API key", _jsx(IconExternalLink, { size: isPage ? 14 : 10 })] })) : null, engineChanged && (_jsx(Button, { intent: "primary", emphasis: "solid", onClick: handleApply, className: pillButtonClass(isPage, "solid"), children: "Apply" })), settingsStatus != null && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { intent: "danger", emphasis: "outline", onClick: handleDisconnect, className: cn(pillButtonClass(isPage, "outline"), "ms-auto text-muted-foreground hover:bg-destructive/10 hover:text-destructive hover:border-destructive/40"), children: "Disconnect" }) }), _jsx(TooltipContent, { children: "Clear the saved engine \u2014 the app will fall back to the default until you re-apply." })] }))] }), testResult && testResult.ok && (_jsxs("p", { className: cn("flex items-center gap-1 text-green-500", isPage ? "text-xs" : "text-[10px]"), children: [_jsx(IconCheck, { size: isPage ? 14 : 10 }), "Test passed \u2014 ", testResult.latencyMs, "ms"] })), testResult && testResult.ok === false && (_jsxs("p", { className: cn("text-destructive", isPage ? "text-xs" : "text-[10px]"), children: ["Test failed: ", testResult.error] })), disconnectError && (_jsxs("p", { className: cn("text-destructive", isPage ? "text-xs" : "text-[10px]"), children: ["Disconnect failed: ", disconnectError] })), applyNote && (_jsx("p", { className: cn("text-muted-foreground", isPage ? "text-xs" : "text-[10px]"), children: "Changes take effect on next conversation" }))] }) }))] })) }));
|
|
580
|
+
}, placeholder: PROVIDER_ENV_PLACEHOLDERS[envVar] ?? "...", className: cn(textInputClass(isPage), "flex-1"), style: isPage ? CONTROL_STYLE_PAGE : undefined }), _jsx(Button, { intent: "primary", emphasis: "solid", onClick: handleSave, disabled: !providerSettingsChanged || saving, className: pillButtonClass(isPage, "solid"), children: saving ? (_jsx(IconLoader2, { size: isPage ? 14 : 10, className: "animate-spin" })) : saved ? (_jsx(IconCheck, { size: isPage ? 14 : 10 })) : ("Save") })] })) : null, _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Button, { intent: "neutral", emphasis: "outline", onClick: handleTest, disabled: testing, className: pillButtonClass(isPage, "outline"), children: testing ? (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(IconLoader2, { size: isPage ? 14 : 10, className: "animate-spin" }), "Testing\u2026"] })) : ("Test") }), PROVIDER_DOCS[selectedEngine] ? (_jsxs("a", { href: PROVIDER_DOCS[selectedEngine], target: "_blank", rel: "noopener noreferrer", className: cn(pillButtonClass(isPage, "outline"), "no-underline"), children: ["Get an API key", _jsx(IconExternalLink, { size: isPage ? 14 : 10 })] })) : null, engineChanged && (_jsx(Button, { intent: "primary", emphasis: "solid", onClick: handleApply, className: pillButtonClass(isPage, "solid"), children: "Apply" })), settingsStatus != null && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(Button, { intent: "danger", emphasis: "outline", onClick: handleDisconnect, className: cn(pillButtonClass(isPage, "outline"), "ms-auto text-muted-foreground hover:bg-destructive/10 hover:text-destructive hover:border-destructive/40"), children: "Disconnect" }) }), _jsx(TooltipContent, { children: "Clear the saved engine \u2014 the app will fall back to the default until you re-apply." })] }))] }), testResult && testResult.ok && (_jsxs("p", { className: cn("flex items-center gap-1 text-primary", isPage ? "text-xs" : "text-[10px]"), children: [_jsx(IconCheck, { size: isPage ? 14 : 10 }), "Test passed \u2014 ", testResult.latencyMs, "ms"] })), testResult && testResult.ok === false && (_jsxs("p", { className: cn("text-destructive", isPage ? "text-xs" : "text-[10px]"), children: ["Test failed: ", testResult.error] })), disconnectError && (_jsxs("p", { className: cn("text-destructive", isPage ? "text-xs" : "text-[10px]"), children: ["Disconnect failed: ", disconnectError] })), applyNote && (_jsx("p", { className: cn("text-muted-foreground", isPage ? "text-xs" : "text-[10px]"), children: "Changes take effect on next conversation" }))] }) }))] })] })) }));
|
|
563
581
|
}
|
|
564
582
|
function friendlyAppName(appId) {
|
|
565
583
|
return appId
|
|
@@ -568,7 +586,47 @@ function friendlyAppName(appId) {
|
|
|
568
586
|
.map((part) => part[0]?.toUpperCase() + part.slice(1))
|
|
569
587
|
.join(" ");
|
|
570
588
|
}
|
|
571
|
-
function
|
|
589
|
+
function AppDefaultModelPicker({ engines, value, disabled, onChange, }) {
|
|
590
|
+
const [open, setOpen] = useState(false);
|
|
591
|
+
const visibleEngines = engines.filter((engine) => engine.name !== "ai-sdk:anthropic" && engine.name !== "ai-sdk:ollama");
|
|
592
|
+
const selectedModel = value.includes("::")
|
|
593
|
+
? value.slice(value.indexOf("::") + 2)
|
|
594
|
+
: null;
|
|
595
|
+
const selectedEngine = value.includes("::")
|
|
596
|
+
? visibleEngines.find((engine) => engine.name === value.split("::", 1)[0])
|
|
597
|
+
: null;
|
|
598
|
+
const selectedLabel = selectedModel
|
|
599
|
+
? `${selectedEngine?.label ?? selectedEngine?.name ?? "Provider"} · ${friendlyModelName(selectedModel)}`
|
|
600
|
+
: "Global default";
|
|
601
|
+
const openIntegrations = () => {
|
|
602
|
+
setOpen(false);
|
|
603
|
+
if (typeof window !== "undefined")
|
|
604
|
+
window.location.hash = "integrations";
|
|
605
|
+
};
|
|
606
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { type: "button", disabled: disabled, "aria-label": "Default model", className: "inline-flex h-10 min-w-[230px] max-w-[320px] items-center justify-between gap-3 rounded-md border border-border bg-background px-3 text-start text-sm text-foreground transition-colors hover:bg-accent/40 disabled:cursor-not-allowed disabled:opacity-60", children: [_jsx("span", { className: "truncate", children: selectedLabel }), _jsx(IconChevronDown, { size: 15, className: "shrink-0 text-muted-foreground" })] }) }), _jsx(PopoverContent, { align: "end", sideOffset: 6, className: "w-[min(380px,calc(100vw-2rem))] p-0", children: _jsxs(Command, { filter: (candidate, search) => candidate.toLowerCase().includes(search.toLowerCase()) ? 1 : 0, children: [_jsx(CommandInput, { placeholder: "Search providers or models..." }), _jsxs(CommandList, { className: "max-h-[min(420px,calc(100vh-8rem))]", children: [_jsx(CommandEmpty, { children: "No models found." }), _jsx(CommandGroup, { heading: "Default", children: _jsxs(CommandItem, { value: "global default shared llm", onSelect: () => {
|
|
607
|
+
onChange("__global__");
|
|
608
|
+
setOpen(false);
|
|
609
|
+
}, className: "items-start gap-2", children: [_jsx(IconCheck, { size: 15, className: cn("mt-0.5 shrink-0", value === "__global__" ? "opacity-100" : "opacity-0") }), _jsxs("span", { className: "flex min-w-0 flex-col", children: [_jsx("span", { children: "Global default" }), _jsx("span", { className: "text-xs text-muted-foreground", children: "Use the shared LLM default" })] })] }) }), visibleEngines.length > 0 && _jsx(CommandSeparator, {}), visibleEngines.map((engine) => {
|
|
610
|
+
const providerLabel = engine.name === "builder"
|
|
611
|
+
? "Builder.io"
|
|
612
|
+
: engine.label || engine.name;
|
|
613
|
+
const modelIds = latestModelsOnly(engine.supportedModels);
|
|
614
|
+
const models = modelIds.length
|
|
615
|
+
? modelIds
|
|
616
|
+
: engine.defaultModel
|
|
617
|
+
? [engine.defaultModel]
|
|
618
|
+
: [];
|
|
619
|
+
const configured = engine.configured && engine.packageInstalled !== false;
|
|
620
|
+
return (_jsxs(CommandGroup, { heading: providerLabel, children: [models.map((model) => {
|
|
621
|
+
const optionValue = `${engine.name}::${model}`;
|
|
622
|
+
return (_jsxs(CommandItem, { value: `${providerLabel} ${model} ${friendlyModelName(model)}`, disabled: !configured, onSelect: () => {
|
|
623
|
+
onChange(optionValue);
|
|
624
|
+
setOpen(false);
|
|
625
|
+
}, className: "items-start gap-2", children: [_jsx(IconCheck, { size: 15, className: cn("mt-0.5 shrink-0", value === optionValue ? "opacity-100" : "opacity-0") }), _jsx("span", { className: "truncate", children: friendlyModelName(model) })] }, optionValue));
|
|
626
|
+
}), !configured && (_jsxs(CommandItem, { value: `configure ${providerLabel} in integrations api keys`, onSelect: openIntegrations, className: "gap-2 text-muted-foreground", children: [_jsx(IconExternalLink, { size: 14 }), "Configure in Integrations"] }))] }, engine.name));
|
|
627
|
+
})] })] }) })] }));
|
|
628
|
+
}
|
|
629
|
+
function AppModelDefaultsSectionInner({ grouped = false, open, onToggle, }) {
|
|
572
630
|
const isPage = useSettingsSurface() === "page";
|
|
573
631
|
const [settings, setSettings] = useState(null);
|
|
574
632
|
const [selectedEngine, setSelectedEngine] = useState("");
|
|
@@ -633,19 +691,28 @@ function AppModelDefaultsSectionInner({ open, onToggle, }) {
|
|
|
633
691
|
const notifyChanged = () => {
|
|
634
692
|
window.dispatchEvent(new CustomEvent("agent-engine:configured-changed"));
|
|
635
693
|
};
|
|
636
|
-
const save = async () => {
|
|
637
|
-
|
|
694
|
+
const save = async (next) => {
|
|
695
|
+
const targetEngine = next?.engine ?? selectedEngine;
|
|
696
|
+
const targetModel = (next?.model ?? selectedModel).trim();
|
|
697
|
+
const targetPendingChange = !!settings &&
|
|
698
|
+
settings.canUpdate &&
|
|
699
|
+
!!targetEngine &&
|
|
700
|
+
!!targetModel &&
|
|
701
|
+
(targetEngine !== settings.engine || targetModel !== settings.model);
|
|
702
|
+
if (!targetPendingChange)
|
|
638
703
|
return;
|
|
639
704
|
setSaving(true);
|
|
640
705
|
setSaved(false);
|
|
641
706
|
setError(null);
|
|
707
|
+
setSelectedEngine(targetEngine);
|
|
708
|
+
setSelectedModel(targetModel);
|
|
642
709
|
try {
|
|
643
710
|
const res = await fetch(agentNativePath("/_agent-native/agent-model-defaults"), {
|
|
644
711
|
method: "PUT",
|
|
645
712
|
headers: { "Content-Type": "application/json" },
|
|
646
713
|
body: JSON.stringify({
|
|
647
|
-
engine:
|
|
648
|
-
model:
|
|
714
|
+
engine: targetEngine,
|
|
715
|
+
model: targetModel,
|
|
649
716
|
}),
|
|
650
717
|
});
|
|
651
718
|
const body = await res.json().catch(() => ({}));
|
|
@@ -691,7 +758,24 @@ function AppModelDefaultsSectionInner({ open, onToggle, }) {
|
|
|
691
758
|
setSaving(false);
|
|
692
759
|
}
|
|
693
760
|
};
|
|
694
|
-
return (_jsx(SettingsSection, { id: settingsSectionDomId("app-models"), icon: _jsx(IconApps, { size: 14 }), title: "App Default Model", subtitle: "Choose the
|
|
761
|
+
return (_jsx(SettingsSection, { id: settingsSectionDomId("app-models"), icon: _jsx(IconApps, { size: 14 }), title: "App Default Model", subtitle: "Choose the model used by this app by default.", connected: loading ? undefined : hasAppDefault, grouped: isPage && grouped, open: open, onToggle: onToggle, children: loading ? (_jsx(SettingsSkeleton, { lines: 2 })) : settings ? (isPage ? (_jsxs(SettingsRow, { className: grouped ? undefined : "-mx-5 sm:-mx-6", label: "Default model", description: hasAppDefault
|
|
762
|
+
? `Used by ${friendlyAppName(settings.appId) || "this app"} · ${scopeLabel}.`
|
|
763
|
+
: "Uses the global LLM default.", status: _jsx("span", { className: "text-xs text-muted-foreground", children: settings.source }), control: _jsx(AppDefaultModelPicker, { engines: settings.engines, value: hasAppDefault
|
|
764
|
+
? `${selectedEngine}::${selectedModel}`
|
|
765
|
+
: "__global__", disabled: !settings.canUpdate || saving, onChange: (next) => {
|
|
766
|
+
const value = next;
|
|
767
|
+
if (value === "__global__") {
|
|
768
|
+
void reset();
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
const separator = value.indexOf("::");
|
|
772
|
+
if (separator < 1)
|
|
773
|
+
return;
|
|
774
|
+
void save({
|
|
775
|
+
engine: value.slice(0, separator),
|
|
776
|
+
model: value.slice(separator + 2),
|
|
777
|
+
});
|
|
778
|
+
} }), children: [!settings.canUpdate && (_jsx("p", { className: "text-xs text-muted-foreground", children: "Only organization owners and admins can change this setting." })), error && _jsx("p", { className: "text-xs text-destructive", children: error })] })) : (_jsx("div", { className: "space-y-2", children: _jsxs("div", { className: cn("rounded-md border border-border bg-accent/20", isPage ? "px-3.5 py-3" : "px-2.5 py-2"), children: [_jsxs("div", { className: "mb-2 flex items-center justify-between gap-2", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: cn("truncate font-medium text-foreground", subTextClass(isPage)), children: friendlyAppName(settings.appId) || "This app" }), _jsx("p", { className: cn("mt-0.5 text-muted-foreground", noteTextClass(isPage)), children: hasAppDefault
|
|
695
779
|
? `Applies to ${scopeLabel}.`
|
|
696
780
|
: "Using the global LLM default." })] }), _jsx("span", { className: cn("shrink-0 rounded-full bg-background px-2 py-0.5 font-medium text-muted-foreground", noteTextClass(isPage)), children: settings.source })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(SettingsSelect, { label: "Provider", value: selectedEngine, options: engineOptions, onValueChange: (value) => {
|
|
697
781
|
setSelectedEngine(value);
|
|
@@ -704,7 +788,7 @@ function AppModelDefaultsSectionInner({ open, onToggle, }) {
|
|
|
704
788
|
}, onEnter: () => {
|
|
705
789
|
if (hasPendingChange)
|
|
706
790
|
void save();
|
|
707
|
-
} }), _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(Button, { type: "button", intent: "primary", emphasis: "solid", onClick: save, disabled: !hasPendingChange || saving, className: pillButtonClass(isPage, "solid"), children: saving ? (_jsx(IconLoader2, { size: isPage ? 14 : 10, className: "animate-spin" })) : saved ? (_jsx(IconCheck, { size: isPage ? 14 : 10 })) : ("Save") }), _jsx(Button, { type: "button", intent: "neutral", emphasis: "outline", onClick: reset, disabled: !settings.canUpdate || !hasAppDefault || saving, className: pillButtonClass(isPage, "outline"), children: "Reset" })] })] }), !settings.canUpdate && (_jsx("p", { className: cn("mt-2 text-muted-foreground", noteTextClass(isPage)), children: "Only organization owners and admins can change app model defaults." })), selectedEngineInfo?.packageInstalled === false ? (_jsx("p", { className: cn("mt-2 text-muted-foreground", noteTextClass(isPage)), children: "This app does not include the optional runtime packages for this provider." })) : selectedEngineInfo && !selectedEngineInfo.configured ? (_jsx("p", { className: cn("mt-2 text-muted-foreground", noteTextClass(isPage)), children: "Credentials for this provider were not detected; runtime will fall back if the model cannot be used." })) : null, error && (_jsx("p", { className: cn("mt-2 text-destructive", noteTextClass(isPage)), children: error }))] }) })) : (_jsx("p", { className: cn("text-muted-foreground", noteTextClass(isPage)), children: "App model defaults are unavailable." })) }));
|
|
791
|
+
} }), _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(Button, { type: "button", intent: "primary", emphasis: "solid", onClick: () => void save(), disabled: !hasPendingChange || saving, className: pillButtonClass(isPage, "solid"), children: saving ? (_jsx(IconLoader2, { size: isPage ? 14 : 10, className: "animate-spin" })) : saved ? (_jsx(IconCheck, { size: isPage ? 14 : 10 })) : ("Save") }), _jsx(Button, { type: "button", intent: "neutral", emphasis: "outline", onClick: reset, disabled: !settings.canUpdate || !hasAppDefault || saving, className: pillButtonClass(isPage, "outline"), children: "Reset" })] })] }), !settings.canUpdate && (_jsx("p", { className: cn("mt-2 text-muted-foreground", noteTextClass(isPage)), children: "Only organization owners and admins can change app model defaults." })), selectedEngineInfo?.packageInstalled === false ? (_jsx("p", { className: cn("mt-2 text-muted-foreground", noteTextClass(isPage)), children: "This app does not include the optional runtime packages for this provider." })) : selectedEngineInfo && !selectedEngineInfo.configured ? (_jsx("p", { className: cn("mt-2 text-muted-foreground", noteTextClass(isPage)), children: "Credentials for this provider were not detected; runtime will fall back if the model cannot be used." })) : null, error && (_jsx("p", { className: cn("mt-2 text-destructive", noteTextClass(isPage)), children: error }))] }) }))) : (_jsx("p", { className: cn("text-muted-foreground", noteTextClass(isPage)), children: "App model defaults are unavailable." })) }));
|
|
708
792
|
}
|
|
709
793
|
// ─── Email Section ──────────────────────────────────────────────────────────
|
|
710
794
|
function EmailSectionInner({ open, onToggle, }) {
|
|
@@ -791,7 +875,7 @@ function EmailSectionInner({ open, onToggle, }) {
|
|
|
791
875
|
saveSendgrid();
|
|
792
876
|
}, placeholder: "From address - e.g. Acme <hi@acme.com>", className: emailInputCls }), !sendgridConfigured ? null : (_jsx(Button, { intent: "primary", emphasis: "solid", onClick: saveSendgrid, disabled: !fromAddr.trim() || saving, className: emailBtnCls, children: saving ? (_jsx(IconLoader2, { size: 10, className: "animate-spin" })) : saved ? (_jsx(IconCheck, { size: 10 })) : ("Save") }))] }))] }))] })) }));
|
|
793
877
|
}
|
|
794
|
-
function AgentLimitsSectionInner({ open, onToggle, }) {
|
|
878
|
+
function AgentLimitsSectionInner({ grouped = false, open, onToggle, }) {
|
|
795
879
|
const isPage = useSettingsSurface() === "page";
|
|
796
880
|
const [settings, setSettings] = useState(null);
|
|
797
881
|
const [value, setValue] = useState("");
|
|
@@ -893,11 +977,21 @@ function AgentLimitsSectionInner({ open, onToggle, }) {
|
|
|
893
977
|
setSaving(false);
|
|
894
978
|
}
|
|
895
979
|
};
|
|
896
|
-
return (_jsx(SettingsSection, { id: settingsSectionDomId("limits"), icon: _jsx(IconGauge, { size: 14 }), title: "Agent Limits", subtitle: "
|
|
980
|
+
return (_jsx(SettingsSection, { id: settingsSectionDomId("limits"), icon: _jsx(IconGauge, { size: 14 }), title: "Agent Limits", subtitle: "Set how long a response can work before pausing.", connected: loading
|
|
897
981
|
? undefined
|
|
898
982
|
: settings
|
|
899
983
|
? settings.maxIterations !== settings.defaultMaxIterations
|
|
900
|
-
: false, open: open, onToggle: onToggle, children: loading ? (_jsx(SettingsSkeleton, { lines: 2 })) : settings ? (_jsx(
|
|
984
|
+
: false, grouped: isPage && grouped, open: open, onToggle: onToggle, children: loading ? (_jsx(SettingsSkeleton, { lines: 2 })) : settings ? (isPage ? (_jsx(SettingsRow, { className: grouped ? undefined : "-mx-5 sm:-mx-6", label: "Max iterations", description: `Default ${settings.defaultMaxIterations.toLocaleString()} · applies to ${scopeLabel}.`, status: _jsx("span", { className: "text-xs text-muted-foreground", children: settings.source }), control: _jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(ManageButton, {}) }), _jsx(PopoverContent, { align: "end", sideOffset: 6, className: "w-80 p-4", children: _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium text-foreground", children: "Max iterations" }), _jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: "Choose how long a response can work before pausing." })] }), _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("input", { type: "number", min: settings.minMaxIterations, max: settings.maxMaxIterations, value: value, disabled: !settings.canUpdate || saving, onChange: (event) => {
|
|
985
|
+
setValue(event.target.value);
|
|
986
|
+
setError(null);
|
|
987
|
+
}, onKeyDown: (event) => {
|
|
988
|
+
if (event.key === "Enter" && hasPendingChange) {
|
|
989
|
+
void save();
|
|
990
|
+
}
|
|
991
|
+
}, className: cn(textInputClass(true), "min-w-0 flex-1 disabled:opacity-60"), style: CONTROL_STYLE_PAGE }), _jsx(Button, { type: "button", intent: "primary", emphasis: "solid", onClick: save, disabled: !hasPendingChange || saving, className: pillButtonClass(true, "solid"), children: saving ? (_jsx(IconLoader2, { size: 14, className: "animate-spin" })) : saved ? (_jsx(IconCheck, { size: 14 })) : ("Save") }), _jsx(Button, { type: "button", intent: "neutral", emphasis: "outline", onClick: reset, disabled: !settings.canUpdate ||
|
|
992
|
+
saving ||
|
|
993
|
+
settings.maxIterations ===
|
|
994
|
+
settings.defaultMaxIterations, className: pillButtonClass(true, "outline"), children: "Reset" })] }), !settings.canUpdate && (_jsx("p", { className: "text-xs text-muted-foreground", children: "Only organization owners and admins can change this limit." })), error && (_jsx("p", { className: "text-xs text-destructive", children: error }))] }) })] }) })) : (_jsx("div", { className: "space-y-2", children: _jsxs("div", { className: cn("rounded-md border border-border bg-accent/20", isPage ? "px-3.5 py-3" : "px-2.5 py-2"), children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("div", { children: [_jsx("p", { className: cn("font-medium text-foreground", subTextClass(isPage)), children: "Max iterations" }), _jsxs("p", { className: cn("mt-0.5 text-muted-foreground", noteTextClass(isPage)), children: ["Applies to ", scopeLabel, ". Default is", " ", settings.defaultMaxIterations.toLocaleString(), "."] })] }), _jsx("span", { className: cn("rounded-full bg-background px-2 py-0.5 font-medium text-muted-foreground", noteTextClass(isPage)), children: settings.source })] }), _jsxs("div", { className: "mt-2 flex items-center gap-1.5", children: [_jsx("input", { type: "number", min: settings.minMaxIterations, max: settings.maxMaxIterations, value: value, disabled: !settings.canUpdate || saving, onChange: (e) => {
|
|
901
995
|
setValue(e.target.value);
|
|
902
996
|
setError(null);
|
|
903
997
|
}, onKeyDown: (e) => {
|
|
@@ -905,27 +999,11 @@ function AgentLimitsSectionInner({ open, onToggle, }) {
|
|
|
905
999
|
void save();
|
|
906
1000
|
}, className: cn(textInputClass(isPage), "min-w-0 flex-1 disabled:opacity-60"), style: isPage ? CONTROL_STYLE_PAGE : undefined }), _jsx(Button, { type: "button", intent: "primary", emphasis: "solid", onClick: save, disabled: !hasPendingChange || saving, className: pillButtonClass(isPage, "solid"), children: saving ? (_jsx(IconLoader2, { size: isPage ? 14 : 10, className: "animate-spin" })) : saved ? (_jsx(IconCheck, { size: isPage ? 14 : 10 })) : ("Save") }), _jsx(Button, { type: "button", intent: "neutral", emphasis: "outline", onClick: reset, disabled: !settings.canUpdate ||
|
|
907
1001
|
saving ||
|
|
908
|
-
settings.maxIterations === settings.defaultMaxIterations, className: pillButtonClass(isPage, "outline"), children: "Reset" })] }), !settings.canUpdate && (_jsx("p", { className: cn("mt-2 text-muted-foreground", noteTextClass(isPage)), children: "Only organization owners and admins can change this limit." })), error && (_jsx("p", { className: cn("mt-2 text-destructive", noteTextClass(isPage)), children: error }))] }) })) : (_jsx("p", { className: cn("text-muted-foreground", noteTextClass(isPage)), children: "Agent limit settings are unavailable." })) }));
|
|
1002
|
+
settings.maxIterations === settings.defaultMaxIterations, className: pillButtonClass(isPage, "outline"), children: "Reset" })] }), !settings.canUpdate && (_jsx("p", { className: cn("mt-2 text-muted-foreground", noteTextClass(isPage)), children: "Only organization owners and admins can change this limit." })), error && (_jsx("p", { className: cn("mt-2 text-destructive", noteTextClass(isPage)), children: error }))] }) }))) : (_jsx("p", { className: cn("text-muted-foreground", noteTextClass(isPage)), children: "Agent limit settings are unavailable." })) }));
|
|
909
1003
|
}
|
|
910
1004
|
export function areExtensionSettingsEnabled(options = {}) {
|
|
911
1005
|
return options.extensionTools === true;
|
|
912
1006
|
}
|
|
913
|
-
// Agent capability modes. The internal values ("production"/"development") are
|
|
914
|
-
// kept for back-compat with the AGENT_MODE wiring; only the visible labels
|
|
915
|
-
// changed to "App mode" / "Code mode" so this control reads as the agent
|
|
916
|
-
// capability it is — not the deployment environment (NODE_ENV).
|
|
917
|
-
const agentModeOptions = [
|
|
918
|
-
{
|
|
919
|
-
value: "production",
|
|
920
|
-
label: "App mode",
|
|
921
|
-
description: "App tools only; code, bash, and files require Builder or a local clone.",
|
|
922
|
-
},
|
|
923
|
-
{
|
|
924
|
-
value: "development",
|
|
925
|
-
label: "Code mode",
|
|
926
|
-
description: "Full access to code editing, bash, and files.",
|
|
927
|
-
},
|
|
928
|
-
];
|
|
929
1007
|
function CapabilityStatusRow({ label, value, active, }) {
|
|
930
1008
|
return (_jsxs("div", { className: "flex items-center justify-between gap-2 text-[10px]", children: [_jsxs("span", { className: "flex items-center gap-1.5 text-muted-foreground", children: [_jsx("span", { className: `h-1.5 w-1.5 rounded-full ${active ? "bg-green-500" : "bg-muted-foreground/30"}`, "aria-hidden": "true" }), label] }), _jsx("span", { className: "min-w-0 truncate text-end text-foreground", children: value })] }));
|
|
931
1009
|
}
|
|
@@ -938,7 +1016,7 @@ function CapabilityStatusStrip({ isDevMode, builderConnected, builderLoading, bu
|
|
|
938
1016
|
: "Desktop/local";
|
|
939
1017
|
return (_jsxs("div", { className: "rounded-md border border-border bg-muted/20 px-2.5 py-2", children: [_jsx("div", { className: "mb-1.5 text-[10px] font-medium text-muted-foreground", children: "Available now" }), _jsxs("div", { className: "space-y-1.5", children: [_jsx(CapabilityStatusRow, { label: "App", value: "Chat + actions", active: true }), _jsx(CapabilityStatusRow, { label: "Code", value: codeLabel, active: codeAvailable }), _jsx(CapabilityStatusRow, { label: "Builder", active: builderConnected, value: builderLoading ? ("Checking...") : builderConnected ? ("Connected") : (_jsx(Button, { type: "button", intent: "neutral", emphasis: "outline", onClick: onOpenLlm, className: "rounded border border-border px-1.5 py-0.5 text-[10px] text-muted-foreground transition-colors hover:bg-accent/40 hover:text-foreground", children: "Connect" })) })] })] }));
|
|
940
1018
|
}
|
|
941
|
-
function SettingsPanelContent({ isDevMode,
|
|
1019
|
+
function SettingsPanelContent({ isDevMode, initialSection, sectionRequestKey, sections = ALL_SETTINGS_SECTIONS, showCapabilityStrip = true, className, surface = "sidebar", builderConnectionOwnedExternally = false, }) {
|
|
942
1020
|
const { status: builder, loading: builderLoading } = useBuilderStatus({
|
|
943
1021
|
enabled: !builderConnectionOwnedExternally,
|
|
944
1022
|
});
|
|
@@ -969,23 +1047,19 @@ function SettingsPanelContent({ isDevMode, onToggleDevMode, showDevToggle, devAp
|
|
|
969
1047
|
});
|
|
970
1048
|
const openSettingsSection = useCallback((section, scroll = false) => openControllerSection(section, { scroll }), [openControllerSection]);
|
|
971
1049
|
const isPage = surface === "page";
|
|
972
|
-
return (_jsx(SettingsSurfaceProvider, { surface: surface, children: _jsxs("div", { className: cn(isPage ? "space-y-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1050
|
+
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 &&
|
|
1051
|
+
["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 &&
|
|
1052
|
+
["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 }) }) }))] })), !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, {}) })), 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 }) })), 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 })] }) })), 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 })] }) })), 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: "Without a provider, files are stored as base64 in your database. Fine for dev, not recommended for production.", 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 })] }) })), 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 &&
|
|
1053
|
+
builderBranchesAvailable &&
|
|
1054
|
+
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, {}) }))] }) }));
|
|
977
1055
|
}
|
|
978
1056
|
export function SettingsPanel(props) {
|
|
979
1057
|
return _jsx(SettingsPanelContent, { ...props });
|
|
980
1058
|
}
|
|
981
|
-
function McpConnectionsCard() {
|
|
982
|
-
const t = useT();
|
|
983
|
-
return (_jsx("section", { className: "rounded-lg border border-border bg-muted/20 p-3", children: _jsxs("div", { className: "flex items-start gap-2.5", children: [_jsx(IconPlugConnected, { size: 16, className: "mt-0.5 shrink-0 text-muted-foreground" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("h2", { className: "text-sm font-semibold text-foreground", children: t("settings.mcpConnectionsTitle") }), _jsx("p", { className: "mt-1 text-xs leading-5 text-muted-foreground", children: t("settings.mcpConnectionsDescription") }), _jsxs(Link, { to: "/agent#connections", className: "mt-2 inline-flex items-center gap-1 text-xs font-medium text-foreground underline-offset-4 hover:underline", children: [t("settings.openMcpConnections"), _jsx(IconExternalLink, { size: 13 })] })] })] }) }));
|
|
984
|
-
}
|
|
985
1059
|
export function ConnectionsSettingsContent({ settingsPanelProps, }) {
|
|
986
|
-
return (_jsxs("div", { className: "
|
|
1060
|
+
return (_jsxs("div", { className: "w-full space-y-8", children: [_jsx(Suspense, { fallback: null, children: _jsx(IntegrationsPanel, {}) }), _jsx(BuilderConnectCard, { trackingSource: "settings_connections" }), _jsx(SettingsPanelContent, { ...settingsPanelProps, surface: "page", sections: INTEGRATION_SETTINGS_SECTIONS.filter((section) => section !== "integrations"), showCapabilityStrip: false, className: "w-full", builderConnectionOwnedExternally: true })] }));
|
|
987
1061
|
}
|
|
988
|
-
export function AgentSettingsContent({ className, } = {}) {
|
|
1062
|
+
export function AgentSettingsContent({ className, sections = AGENT_SETTINGS_SECTIONS, } = {}) {
|
|
989
1063
|
const { isDevMode, canToggle, setDevMode } = useDevMode();
|
|
990
1064
|
const settingsPanelProps = useMemo(() => ({
|
|
991
1065
|
isDevMode,
|
|
@@ -994,7 +1068,7 @@ export function AgentSettingsContent({ className, } = {}) {
|
|
|
994
1068
|
},
|
|
995
1069
|
showDevToggle: canToggle,
|
|
996
1070
|
}), [canToggle, isDevMode, setDevMode]);
|
|
997
|
-
return (_jsx(SettingsPanelContent, { ...settingsPanelProps, surface: "page", sections:
|
|
1071
|
+
return (_jsx(SettingsPanelContent, { ...settingsPanelProps, surface: "page", sections: sections, showCapabilityStrip: false, className: cn("w-full", className) }));
|
|
998
1072
|
}
|
|
999
1073
|
export function useAgentSettingsTabs(options = {}) {
|
|
1000
1074
|
const { isDevMode, canToggle, setDevMode } = useDevMode();
|
|
@@ -1015,27 +1089,93 @@ export function useAgentSettingsTabs(options = {}) {
|
|
|
1015
1089
|
return tab;
|
|
1016
1090
|
};
|
|
1017
1091
|
const agent = searchTab("agent");
|
|
1018
|
-
const
|
|
1092
|
+
const integrations = searchTab("integrations");
|
|
1019
1093
|
const organization = searchTab("organization");
|
|
1020
1094
|
const workspace = searchTab("workspace");
|
|
1095
|
+
const overviewSearchEntries = (agent.searchEntries ?? []).filter((entry) => entry.hash !== "automations" && entry.hash !== "a2a");
|
|
1096
|
+
const resourceSearchEntries = [
|
|
1097
|
+
{
|
|
1098
|
+
id: "agent-resource-files",
|
|
1099
|
+
label: "Files",
|
|
1100
|
+
keywords: "files uploads documents context resources",
|
|
1101
|
+
description: "Agent resources",
|
|
1102
|
+
tabId: "agent:resources",
|
|
1103
|
+
hash: "agent:resources:files",
|
|
1104
|
+
icon: IconFolder,
|
|
1105
|
+
},
|
|
1106
|
+
{
|
|
1107
|
+
id: "agent-resource-instructions",
|
|
1108
|
+
label: "Instructions",
|
|
1109
|
+
keywords: "instructions agents md behavior context",
|
|
1110
|
+
description: "Agent resources",
|
|
1111
|
+
tabId: "agent:resources",
|
|
1112
|
+
hash: "agent:resources:instructions",
|
|
1113
|
+
icon: IconFolder,
|
|
1114
|
+
},
|
|
1115
|
+
{
|
|
1116
|
+
id: "agent-resource-memory",
|
|
1117
|
+
label: "Memory",
|
|
1118
|
+
keywords: "memory personalization context",
|
|
1119
|
+
description: "Agent resources",
|
|
1120
|
+
tabId: "agent:resources",
|
|
1121
|
+
hash: "agent:resources:memory",
|
|
1122
|
+
icon: IconFolder,
|
|
1123
|
+
},
|
|
1124
|
+
{
|
|
1125
|
+
id: "agent-resource-agents",
|
|
1126
|
+
label: "Agents",
|
|
1127
|
+
keywords: "agents custom agents delegate",
|
|
1128
|
+
description: "Agent resources",
|
|
1129
|
+
tabId: "agent:resources",
|
|
1130
|
+
hash: "agent:resources:agents",
|
|
1131
|
+
icon: IconFolder,
|
|
1132
|
+
},
|
|
1133
|
+
{
|
|
1134
|
+
id: "agent-resource-skills",
|
|
1135
|
+
label: "Skills",
|
|
1136
|
+
keywords: "skills tools capabilities",
|
|
1137
|
+
description: "Agent resources",
|
|
1138
|
+
tabId: "agent:resources",
|
|
1139
|
+
hash: "agent:resources:skills",
|
|
1140
|
+
icon: IconFolder,
|
|
1141
|
+
},
|
|
1142
|
+
{
|
|
1143
|
+
id: "agent-resource-learnings",
|
|
1144
|
+
label: "Learnings",
|
|
1145
|
+
keywords: "learnings feedback memory",
|
|
1146
|
+
description: "Agent resources",
|
|
1147
|
+
tabId: "agent:resources",
|
|
1148
|
+
hash: "agent:resources:learnings",
|
|
1149
|
+
icon: IconFolder,
|
|
1150
|
+
},
|
|
1151
|
+
{
|
|
1152
|
+
id: "agent-resource-remote-agents",
|
|
1153
|
+
label: "Remote agents",
|
|
1154
|
+
keywords: "remote agents connected a2a",
|
|
1155
|
+
description: "Agent resources",
|
|
1156
|
+
tabId: "agent:resources",
|
|
1157
|
+
hash: "agent:resources:remote-agents",
|
|
1158
|
+
icon: IconFolder,
|
|
1159
|
+
},
|
|
1160
|
+
];
|
|
1021
1161
|
return [
|
|
1022
1162
|
{
|
|
1023
|
-
...
|
|
1163
|
+
...integrations,
|
|
1024
1164
|
icon: IconPlugConnected,
|
|
1025
|
-
group: "
|
|
1165
|
+
group: "integrations",
|
|
1026
1166
|
content: _jsx(ConnectionsSettingsContent, { settingsPanelProps: baseProps }),
|
|
1027
1167
|
},
|
|
1028
1168
|
{
|
|
1029
1169
|
...organization,
|
|
1030
1170
|
icon: IconUsersGroup,
|
|
1031
1171
|
group: "workspace",
|
|
1032
|
-
content: (_jsx("div", { className: "
|
|
1172
|
+
content: (_jsx("div", { className: "w-full", children: _jsx(TeamPage, { showTitle: false }) })),
|
|
1033
1173
|
},
|
|
1034
1174
|
{
|
|
1035
1175
|
...workspace,
|
|
1036
1176
|
icon: IconCloud,
|
|
1037
1177
|
group: "workspace",
|
|
1038
|
-
content: (_jsx(SettingsPanelContent, { ...baseProps, surface: "page", sections: WORKSPACE_SETTINGS_SECTIONS, showCapabilityStrip: false, className: "
|
|
1178
|
+
content: (_jsx(SettingsPanelContent, { ...baseProps, surface: "page", sections: WORKSPACE_SETTINGS_SECTIONS, showCapabilityStrip: false, className: "w-full" })),
|
|
1039
1179
|
},
|
|
1040
1180
|
...(extensionToolsEnabled
|
|
1041
1181
|
? [
|
|
@@ -1050,12 +1190,68 @@ export function useAgentSettingsTabs(options = {}) {
|
|
|
1050
1190
|
]
|
|
1051
1191
|
: []),
|
|
1052
1192
|
{
|
|
1053
|
-
|
|
1193
|
+
id: "agent",
|
|
1194
|
+
label: "Overview",
|
|
1054
1195
|
icon: IconHierarchy2,
|
|
1055
|
-
group: "
|
|
1056
|
-
|
|
1057
|
-
searchEntries:
|
|
1058
|
-
content: _jsx(
|
|
1196
|
+
group: "agent",
|
|
1197
|
+
keywords: agent.keywords,
|
|
1198
|
+
searchEntries: overviewSearchEntries,
|
|
1199
|
+
content: (_jsx(AgentWorkspaceContent, { activeTab: "overview", overview: _jsx(AgentSettingsContent, { className: "w-full", sections: AGENT_SETTINGS_SECTIONS.filter((section) => section !== "automations" && section !== "a2a") }) })),
|
|
1200
|
+
},
|
|
1201
|
+
{
|
|
1202
|
+
id: "agent:resources",
|
|
1203
|
+
label: "Resources",
|
|
1204
|
+
icon: IconFolder,
|
|
1205
|
+
group: "agent",
|
|
1206
|
+
keywords: "resources files instructions agents memory skills learnings remote agents",
|
|
1207
|
+
searchEntries: resourceSearchEntries,
|
|
1208
|
+
content: (_jsx(AgentWorkspaceContent, { activeTab: "resources", overview: null })),
|
|
1209
|
+
},
|
|
1210
|
+
{
|
|
1211
|
+
id: "agent:automations",
|
|
1212
|
+
label: "Automations",
|
|
1213
|
+
icon: IconBolt,
|
|
1214
|
+
group: "agent",
|
|
1215
|
+
keywords: "automations scheduled events cron jobs tasks",
|
|
1216
|
+
searchEntries: [
|
|
1217
|
+
{
|
|
1218
|
+
id: "section:automations",
|
|
1219
|
+
label: "Automations",
|
|
1220
|
+
keywords: "scheduled events cron jobs tasks",
|
|
1221
|
+
description: "Agent workflows",
|
|
1222
|
+
tabId: "agent:automations",
|
|
1223
|
+
hash: "agent:automations",
|
|
1224
|
+
icon: IconBolt,
|
|
1225
|
+
},
|
|
1226
|
+
],
|
|
1227
|
+
content: (_jsx(AgentWorkspaceContent, { activeTab: "automations", overview: null })),
|
|
1228
|
+
},
|
|
1229
|
+
{
|
|
1230
|
+
id: "agent:agents",
|
|
1231
|
+
label: "Connected agents",
|
|
1232
|
+
icon: IconTopologyRing2,
|
|
1233
|
+
group: "agent",
|
|
1234
|
+
keywords: "connected agents remote agents a2a delegate",
|
|
1235
|
+
searchEntries: [
|
|
1236
|
+
{
|
|
1237
|
+
id: "section:a2a",
|
|
1238
|
+
label: "Connected agents",
|
|
1239
|
+
keywords: "remote agents a2a delegate",
|
|
1240
|
+
description: "Agent access",
|
|
1241
|
+
tabId: "agent:agents",
|
|
1242
|
+
hash: "agent:agents",
|
|
1243
|
+
icon: IconTopologyRing2,
|
|
1244
|
+
},
|
|
1245
|
+
],
|
|
1246
|
+
content: _jsx(AgentWorkspaceContent, { activeTab: "agents", overview: null }),
|
|
1247
|
+
},
|
|
1248
|
+
{
|
|
1249
|
+
id: "agent:access",
|
|
1250
|
+
label: "Access",
|
|
1251
|
+
icon: IconShieldLock,
|
|
1252
|
+
group: "agent",
|
|
1253
|
+
keywords: "access sharing permissions clients",
|
|
1254
|
+
content: _jsx(AgentWorkspaceContent, { activeTab: "access", overview: null }),
|
|
1059
1255
|
},
|
|
1060
1256
|
];
|
|
1061
1257
|
}, [baseProps, extensionToolsEnabled]);
|