@agent-native/core 0.147.0 → 0.148.1
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/frontend-design/SKILL.md +115 -68
- package/corpus/templates/analytics/DEVELOPING.md +50 -3
- package/corpus/templates/analytics/actions/purge-first-party-analytics-postgres.ts +190 -0
- package/corpus/templates/analytics/app/i18n/index.ts +14 -29
- package/corpus/templates/analytics/app/i18n-data.ts +10 -10
- package/corpus/templates/analytics/app/pages/Settings.tsx +5 -21
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -3
- package/corpus/templates/analytics/scripts/first-party-analytics-bigquery-backfill.ts +197 -18
- package/corpus/templates/analytics/server/db/schema.ts +23 -0
- package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +3 -1
- package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +1 -1
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +113 -13
- package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +140 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-volume.ts +207 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +40 -9
- package/corpus/templates/analytics/server/lib/gcloud.ts +148 -20
- package/corpus/templates/analytics/server/plugins/db.ts +42 -0
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/assets/app/i18n/index.ts +14 -29
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/brain/app/i18n/index.ts +14 -29
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/chat/app/i18n/index.ts +14 -29
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -7
- package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +18 -13
- package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +87 -370
- package/corpus/templates/clips/app/components/settings/slack-section.tsx +59 -101
- package/corpus/templates/clips/app/components/settings/video-storage-section.tsx +136 -213
- package/corpus/templates/clips/app/i18n/en-US.ts +11 -8
- package/corpus/templates/clips/desktop/src/app.tsx +1 -1
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/content/app/i18n/index.ts +14 -29
- package/corpus/templates/crm/app/i18n/index.ts +14 -29
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/design/actions/analyze-brand-assets.ts +15 -15
- package/corpus/templates/design/actions/import-code.ts +2 -43
- package/corpus/templates/design/app/i18n/index.ts +14 -29
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/dispatch/app/i18n-data.ts +1 -1
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/factory/AGENTS.md +40 -49
- package/corpus/templates/factory/actions/babysit-agent-native-pull-request.ts +66 -0
- package/corpus/templates/factory/actions/evaluate-triage-item.ts +37 -0
- package/corpus/templates/factory/actions/get-slack-feedback-context.ts +20 -0
- package/corpus/templates/factory/actions/get-triage-item.ts +25 -4
- package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +55 -0
- package/corpus/templates/factory/actions/ingest-github-observation.ts +21 -0
- package/corpus/templates/factory/actions/list-factory-audit.ts +118 -0
- package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
- package/corpus/templates/factory/actions/list-triage-items.ts +24 -2
- package/corpus/templates/factory/actions/poll-github-sources.ts +60 -0
- package/corpus/templates/factory/actions/poll-sentry-errors.ts +39 -0
- package/corpus/templates/factory/actions/poll-slack-channel.ts +45 -1
- package/corpus/templates/factory/actions/run-factory-automation.ts +1 -1
- package/corpus/templates/factory/actions/save-factory-automation.ts +2 -2
- package/corpus/templates/factory/actions/start-builder-for-item.ts +51 -0
- package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +685 -0
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +6 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +25 -0
- package/corpus/templates/factory/app/routes/factory.tsx +95 -42
- package/corpus/templates/factory/server/db/schema.ts +37 -0
- package/corpus/templates/factory/server/lib/require-factory-automation.ts +5 -1
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +29 -0
- package/corpus/templates/factory/server/triage/audit.ts +79 -0
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/forms/app/i18n/index.ts +14 -29
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/macros/app/i18n/index.ts +14 -29
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/mail/app/i18n/index.ts +14 -29
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +7 -7
- package/corpus/templates/plan/app/i18n/index.ts +14 -29
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/slides/actions/analyze-brand-assets.ts +15 -15
- package/corpus/templates/slides/actions/import-code.ts +2 -43
- package/corpus/templates/slides/app/i18n/index.ts +14 -29
- package/corpus/templates/slides/server/routes/api/preview-images.get.ts +4 -1
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/tasks/app/components/layout/HeaderActions.tsx +1 -84
- package/corpus/templates/tasks/app/hooks/use-mobile.tsx +1 -21
- package/corpus/templates/tasks/app/i18n/index.ts +14 -29
- package/dist/agent/engine/ai-sdk-engine.js +2 -1
- package/dist/agent/engine/openai-compatible-endpoint.d.ts +2 -0
- package/dist/agent/engine/openai-compatible-endpoint.js +5 -1
- package/dist/agent/engine/provider-endpoint-validation.d.ts +9 -0
- package/dist/agent/engine/provider-endpoint-validation.js +26 -0
- package/dist/agent/engine/provider-env-vars.d.ts +1 -1
- package/dist/agent/engine/provider-env-vars.js +1 -1
- package/dist/agent/engine/registry.d.ts +8 -6
- package/dist/agent/engine/registry.js +37 -24
- package/dist/agent/tool-search.d.ts +1 -0
- package/dist/agent/tool-search.js +17 -1
- package/dist/automations/service.js +4 -10
- package/dist/brand-kit/brand-signals.d.ts +13 -0
- package/dist/brand-kit/brand-signals.js +15 -0
- package/dist/brand-kit/index.d.ts +2 -2
- package/dist/brand-kit/index.js +1 -1
- package/dist/cli/plan-blocks.d.ts +3 -18
- package/dist/cli/plan-blocks.js +2 -95
- package/dist/cli/plan-publish-store.d.ts +2 -61
- package/dist/cli/plan-publish-store.js +2 -127
- package/dist/cli/skills-content/connection.d.ts +1 -1
- package/dist/cli/skills-content/connection.js +1 -52
- package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
- package/dist/cli/skills-content/visual-recap-skill.js +1 -553
- package/dist/client/agent-engine-key.d.ts +14 -4
- package/dist/client/agent-engine-key.js +51 -5
- package/dist/client/agent-provider-catalog.d.ts +20 -0
- package/dist/client/agent-provider-catalog.js +100 -0
- package/dist/client/blocks/index.d.ts +1 -0
- package/dist/client/blocks/index.js +1 -0
- package/dist/client/blocks/library/diagram.js +1 -1
- package/dist/client/blocks/library/sanitize-html.js +66 -2
- package/dist/client/blocks/library/wireframe-kit.js +69 -0
- package/dist/client/chat/run-recovery.js +4 -48
- package/dist/client/chat-first/apps-rail.d.ts +1 -1
- package/dist/client/chat-first/apps-rail.js +4 -4
- package/dist/client/chat-first/copy.js +1 -0
- package/dist/client/chat-first/types.d.ts +1 -0
- package/dist/client/chat-first.js +4 -3
- package/dist/client/i18n.d.ts +14 -0
- package/dist/client/i18n.js +18 -0
- package/dist/client/settings/ProviderSetupForm.d.ts +21 -0
- package/dist/client/settings/ProviderSetupForm.js +145 -0
- package/dist/client/settings/SettingsPanel.js +52 -49
- package/dist/client/settings/index.d.ts +2 -0
- package/dist/client/settings/index.js +2 -0
- package/dist/coding-tools/run-code.d.ts +5 -0
- package/dist/coding-tools/run-code.js +196 -36
- package/dist/coding-tools/tool-orchestration.d.ts +10 -0
- package/dist/coding-tools/tool-orchestration.js +107 -0
- package/dist/collab/routes.d.ts +1 -1
- package/dist/jobs/frontmatter.d.ts +9 -0
- package/dist/jobs/frontmatter.js +16 -0
- package/dist/jobs/scheduler.js +8 -8
- package/dist/jobs/tools.d.ts +1 -1
- package/dist/jobs/tools.js +2 -7
- package/dist/localization/default-messages.d.ts +20 -0
- package/dist/localization/default-messages.js +25 -5
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +2 -2
- package/dist/onboarding/app-profile.js +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/scripts/agent-engines/test-agent-engine.js +34 -10
- package/dist/server/agent-chat/run-code-tools.d.ts +1 -1
- package/dist/server/agent-chat/run-code-tools.js +3 -1
- package/dist/server/agent-chat-plugin.js +6 -6
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.js +43 -12
- package/dist/server/agents-bundle.js +2 -1
- package/dist/server/auth.js +21 -5
- package/dist/server/credential-provider.js +1 -0
- package/dist/server/design-token-utils.d.ts +18 -0
- package/dist/server/design-token-utils.js +31 -0
- package/dist/server/onboarding-html.js +22 -2
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/styles/blocks.css +132 -0
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/templates/chat/app/i18n/index.ts +14 -29
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/templates/default/app/i18n/index.ts +14 -29
- package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/triggers/dispatcher.js +1 -8
- package/docs/content/actions.mdx +4 -1
- package/docs/content/agent-surfaces.mdx +8 -6
- package/docs/content/automations.mdx +1 -1
- package/docs/content/database.mdx +6 -1
- package/docs/content/docs-components.mdx +22 -14
- package/docs/content/drop-in-agent.mdx +1 -1
- package/docs/content/environment-variables.mdx +39 -38
- package/docs/content/getting-started-actions.mdx +5 -4
- package/docs/content/getting-started-pages.mdx +7 -6
- package/docs/content/getting-started.mdx +4 -3
- package/docs/content/notifications.mdx +6 -6
- package/docs/content/progress.mdx +5 -5
- package/docs/content/routing.mdx +3 -1
- package/docs/content/server-database.mdx +13 -4
- package/docs/content/server-overview.mdx +9 -9
- package/docs/content/server-plugins.mdx +10 -4
- package/docs/content/server-routes.mdx +7 -2
- package/docs/content/tracking.mdx +4 -4
- package/docs/content/what-is-agent-native.mdx +4 -4
- package/package.json +4 -4
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/src/templates/chat/app/i18n/index.ts +14 -29
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
- package/src/templates/default/app/i18n/index.ts +14 -29
- package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/plan/app/components/plan/wireframe/sanitize-html.ts +0 -343
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@agent-native/toolkit/ui/command";
|
|
3
|
+
import { IconBolt, IconCheck, IconChevronDown, IconCloud, IconDeviceDesktop, IconExternalLink, IconKey, IconLoader2, IconRoute, IconServer2, } from "@tabler/icons-react";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
import { saveAgentEngineProviderSettings, setAgentEngineProvider, } from "../agent-engine-key.js";
|
|
6
|
+
import { AGENT_PROVIDER_CATALOG, getAgentProviderOption, } from "../agent-provider-catalog.js";
|
|
7
|
+
import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
|
|
8
|
+
import { useT } from "../i18n.js";
|
|
9
|
+
import { cn } from "../utils.js";
|
|
10
|
+
function ProviderIcon({ option, size = 15, }) {
|
|
11
|
+
if (option.kind === "local")
|
|
12
|
+
return _jsx(IconDeviceDesktop, { size: size });
|
|
13
|
+
if (option.kind === "gateway")
|
|
14
|
+
return _jsx(IconRoute, { size: size });
|
|
15
|
+
return _jsx(IconCloud, { size: size });
|
|
16
|
+
}
|
|
17
|
+
export function AgentProviderPicker({ value, onChange, options = AGENT_PROVIDER_CATALOG, configuredProviders, disabled = false, className, layout = "compact", }) {
|
|
18
|
+
const t = useT();
|
|
19
|
+
const [open, setOpen] = useState(false);
|
|
20
|
+
const active = getAgentProviderOption(value);
|
|
21
|
+
const isPage = layout === "page";
|
|
22
|
+
return (_jsxs("div", { className: cn("space-y-1.5", className), children: [_jsx("p", { className: cn("font-medium text-foreground", isPage ? "text-sm" : "text-[11px]"), children: t("agentPanel.chooseProvider", {
|
|
23
|
+
defaultValue: "Choose a provider",
|
|
24
|
+
}) }), _jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", disabled: disabled, "aria-label": t("agentPanel.chooseProvider", {
|
|
25
|
+
defaultValue: "Choose a provider",
|
|
26
|
+
}), className: cn("flex w-full items-center gap-2 rounded-md border border-border bg-background text-start text-foreground transition-colors hover:bg-accent/40 disabled:cursor-not-allowed disabled:opacity-60", isPage ? "min-h-10 px-3 text-sm" : "min-h-9 px-2.5 text-[12px]"), children: [_jsx("span", { className: "flex size-6 shrink-0 items-center justify-center rounded-md bg-accent/50 text-muted-foreground", children: _jsx(ProviderIcon, { option: active, size: isPage ? 16 : 14 }) }), _jsx("span", { className: "min-w-0 flex-1", children: _jsx("span", { className: "block truncate font-medium", children: active.label }) }), _jsx(IconChevronDown, { size: isPage ? 16 : 14, className: "shrink-0 text-muted-foreground" })] }) }), _jsx(PopoverContent, { align: "start", sideOffset: 6, className: "w-[min(390px,calc(100vw-2rem))] p-0", children: _jsxs(Command, { filter: (candidate, search) => candidate.toLowerCase().includes(search.toLowerCase()) ? 1 : 0, children: [_jsx(CommandInput, { placeholder: t("agentPanel.searchProviders", {
|
|
27
|
+
defaultValue: "Search providers...",
|
|
28
|
+
}) }), _jsxs(CommandList, { className: "max-h-[min(440px,calc(100vh-8rem))]", children: [_jsx(CommandEmpty, { children: t("agentPanel.noProvidersFound", {
|
|
29
|
+
defaultValue: "No providers found.",
|
|
30
|
+
}) }), _jsx(CommandGroup, { heading: t("agentPanel.availableProviders", {
|
|
31
|
+
defaultValue: "Available providers",
|
|
32
|
+
}), children: options.map((option) => {
|
|
33
|
+
const configured = configuredProviders?.has(option.id);
|
|
34
|
+
return (_jsxs(CommandItem, { value: `${option.label} ${option.description} ${option.key ?? "local"}`, onSelect: () => {
|
|
35
|
+
onChange(option.id);
|
|
36
|
+
setOpen(false);
|
|
37
|
+
}, className: "items-center gap-2.5 py-2.5", children: [_jsx("span", { className: "flex size-7 shrink-0 items-center justify-center rounded-md bg-accent/50 text-muted-foreground", children: _jsx(ProviderIcon, { option: option }) }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx("span", { className: "truncate font-medium", children: option.label }), configured ? (_jsxs("span", { className: "inline-flex shrink-0 items-center gap-1 text-[10px] font-medium text-primary", children: [_jsx(IconCheck, { size: 11 }), t("agentPanel.configured", {
|
|
38
|
+
defaultValue: "Configured",
|
|
39
|
+
})] })) : null] }), _jsx("span", { className: "block truncate text-[11px] text-muted-foreground", children: option.description })] }), _jsx("span", { className: "shrink-0 text-[10px] text-muted-foreground", children: option.key
|
|
40
|
+
? t("agentPanel.apiKey", {
|
|
41
|
+
defaultValue: "API key",
|
|
42
|
+
})
|
|
43
|
+
: t("agentPanel.localRuntime", {
|
|
44
|
+
defaultValue: "Local",
|
|
45
|
+
}) }), _jsx(IconCheck, { size: 15, className: cn("shrink-0", option.id === value ? "opacity-100" : "opacity-0") })] }, option.id));
|
|
46
|
+
}) })] })] }) })] })] }));
|
|
47
|
+
}
|
|
48
|
+
export function AgentProviderSetupForm({ initialProvider = "anthropic", configuredProviders, onConnected, scope = "user", layout = "compact", showTitle = true, className, }) {
|
|
49
|
+
const t = useT();
|
|
50
|
+
const isPage = layout === "page";
|
|
51
|
+
const [provider, setProvider] = useState(initialProvider);
|
|
52
|
+
const [apiKey, setApiKey] = useState("");
|
|
53
|
+
const [model, setModel] = useState("");
|
|
54
|
+
const [endpoint, setEndpoint] = useState("");
|
|
55
|
+
const [endpointOpen, setEndpointOpen] = useState(initialProvider === "ollama");
|
|
56
|
+
const [saving, setSaving] = useState(false);
|
|
57
|
+
const [saved, setSaved] = useState(false);
|
|
58
|
+
const [error, setError] = useState(null);
|
|
59
|
+
const active = getAgentProviderOption(provider);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
setModel(active.defaultModel);
|
|
62
|
+
setApiKey("");
|
|
63
|
+
setEndpoint("");
|
|
64
|
+
setEndpointOpen(provider === "ollama");
|
|
65
|
+
setError(null);
|
|
66
|
+
setSaved(false);
|
|
67
|
+
}, [active.defaultModel, provider]);
|
|
68
|
+
const handleProviderChange = (nextProvider) => {
|
|
69
|
+
setProvider(nextProvider);
|
|
70
|
+
};
|
|
71
|
+
const handleSave = async () => {
|
|
72
|
+
if (saving)
|
|
73
|
+
return;
|
|
74
|
+
if (active.key && !apiKey.trim()) {
|
|
75
|
+
setError(t("agentPanel.enterApiKey", {
|
|
76
|
+
defaultValue: `Enter your ${active.label} API key.`,
|
|
77
|
+
}));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
setSaving(true);
|
|
81
|
+
setError(null);
|
|
82
|
+
try {
|
|
83
|
+
if (active.key || endpoint.trim()) {
|
|
84
|
+
await saveAgentEngineProviderSettings({
|
|
85
|
+
provider,
|
|
86
|
+
...(active.key ? { key: active.key } : {}),
|
|
87
|
+
...(apiKey.trim() ? { apiKey } : {}),
|
|
88
|
+
...(endpoint.trim() ? { baseUrl: endpoint } : {}),
|
|
89
|
+
scope,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
await setAgentEngineProvider({
|
|
93
|
+
provider,
|
|
94
|
+
model: model.trim() || active.defaultModel,
|
|
95
|
+
});
|
|
96
|
+
setApiKey("");
|
|
97
|
+
setSaved(true);
|
|
98
|
+
onConnected?.(provider);
|
|
99
|
+
window.setTimeout(() => setSaved(false), 2200);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
setError(err instanceof Error
|
|
103
|
+
? err.message
|
|
104
|
+
: t("agentPanel.providerSetupFailed", {
|
|
105
|
+
defaultValue: "Could not configure this provider.",
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
setSaving(false);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const isConfigured = configuredProviders?.has(provider) || saved;
|
|
113
|
+
const modelInputVisible = active.supportsCustomModel;
|
|
114
|
+
const endpointVisible = active.supportsEndpoint;
|
|
115
|
+
return (_jsxs("form", { className: cn("space-y-3", className), onSubmit: (event) => {
|
|
116
|
+
event.preventDefault();
|
|
117
|
+
void handleSave();
|
|
118
|
+
}, children: [showTitle ? (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(IconKey, { size: isPage ? 16 : 13, className: "text-muted-foreground" }), _jsx("h4", { className: cn("font-medium text-foreground", isPage ? "text-sm" : "text-[11px]"), children: t("agentPanel.addOwnKeys", {
|
|
119
|
+
defaultValue: "Custom keys",
|
|
120
|
+
}) })] }), _jsx("p", { className: cn("mt-1 leading-relaxed text-muted-foreground", isPage ? "text-xs" : "text-[11px]"), children: t("agentPanel.configureProviderKeys", {
|
|
121
|
+
defaultValue: "Choose a provider.",
|
|
122
|
+
}) })] })) : null, _jsx(AgentProviderPicker, { value: provider, onChange: handleProviderChange, configuredProviders: configuredProviders, disabled: saving, layout: layout }), _jsxs("div", { className: cn("rounded-md border border-border bg-accent/20", isPage ? "space-y-3 p-3.5" : "space-y-2.5 p-2.5"), children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 flex size-6 shrink-0 items-center justify-center rounded-md bg-background text-muted-foreground", children: active.kind === "local" ? (_jsx(IconDeviceDesktop, { size: isPage ? 15 : 13 })) : active.kind === "gateway" ? (_jsx(IconRoute, { size: isPage ? 15 : 13 })) : (_jsx(IconBolt, { size: isPage ? 15 : 13 })) }), _jsx("div", { className: "min-w-0 flex-1", title: active.description, children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("p", { className: cn("font-medium text-foreground", isPage ? "text-sm" : "text-[12px]"), children: active.label }), isConfigured ? (_jsxs("span", { className: "inline-flex items-center gap-1 text-[10px] font-medium text-primary", children: [_jsx(IconCheck, { size: 11 }), t("agentPanel.configured", {
|
|
123
|
+
defaultValue: "Configured",
|
|
124
|
+
})] })) : null] }) })] }), active.key ? (_jsxs("label", { className: "block space-y-1.5", children: [_jsx("span", { className: cn("font-medium text-foreground", isPage ? "text-xs" : "text-[11px]"), children: t("agentPanel.apiKey", { defaultValue: "API key" }) }), _jsx("input", { type: "password", value: apiKey, autoComplete: "off", spellCheck: false, placeholder: active.placeholder, disabled: saving, onChange: (event) => {
|
|
125
|
+
setApiKey(event.target.value);
|
|
126
|
+
if (error)
|
|
127
|
+
setError(null);
|
|
128
|
+
}, className: cn("w-full rounded-md border border-input bg-background text-foreground outline-none transition-colors hover:bg-accent/40 focus:ring-1 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background placeholder:text-muted-foreground/50", isPage ? "h-10 px-3 text-sm" : "h-8 px-2.5 text-[12px]") })] })) : (_jsxs("div", { className: "flex items-start gap-2 rounded-md border border-border/70 bg-background/60 px-2.5 py-2", children: [_jsx(IconServer2, { size: isPage ? 15 : 13, className: "mt-0.5 shrink-0 text-muted-foreground" }), _jsx("p", { className: "text-[11px] leading-relaxed text-muted-foreground", children: t("agentPanel.noApiKeyNeeded", {
|
|
129
|
+
defaultValue: "No API key required.",
|
|
130
|
+
}) })] })), modelInputVisible ? (_jsxs("label", { className: "block space-y-1.5", children: [_jsx("span", { className: cn("font-medium text-foreground", isPage ? "text-xs" : "text-[11px]"), children: t("agentPanel.modelId", { defaultValue: "Model ID" }) }), _jsx("input", { type: "text", value: model, list: `agent-provider-models-${provider}`, disabled: saving, spellCheck: false, autoComplete: "off", placeholder: active.defaultModel, onChange: (event) => setModel(event.target.value), className: cn("w-full rounded-md border border-input bg-background text-foreground outline-none transition-colors hover:bg-accent/40 focus:ring-1 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background placeholder:text-muted-foreground/50", isPage ? "h-10 px-3 text-sm" : "h-8 px-2.5 text-[12px]") }), _jsx("datalist", { id: `agent-provider-models-${provider}`, children: active.supportedModels.map((modelOption) => (_jsx("option", { value: modelOption }, modelOption))) })] })) : null, endpointVisible ? (_jsxs("div", { className: "border-t border-border/70 pt-2", children: [_jsxs("button", { type: "button", onClick: () => setEndpointOpen((open) => !open), className: "flex w-full items-center justify-between gap-2 text-start text-[11px] font-medium text-foreground", "aria-expanded": endpointOpen, title: provider === "ollama"
|
|
131
|
+
? "Defaults to Ollama at http://localhost:11434."
|
|
132
|
+
: "Use for LiteLLM or another OpenAI-compatible gateway.", children: [_jsxs("span", { className: "inline-flex items-center gap-1.5", children: [_jsx(IconChevronDown, { size: 13, className: cn("text-muted-foreground transition-transform", !endpointOpen && "-rotate-90") }), t("agentPanel.endpointUrl", {
|
|
133
|
+
defaultValue: "Endpoint URL",
|
|
134
|
+
})] }), _jsx("span", { className: "text-[10px] font-normal text-muted-foreground", children: t("agentPanel.optional", { defaultValue: "Optional" }) })] }), endpointOpen ? (_jsx("div", { className: "mt-2 space-y-1.5", children: _jsx("input", { type: "url", value: endpoint, disabled: saving, spellCheck: false, autoComplete: "off", placeholder: active.endpointPlaceholder, onChange: (event) => setEndpoint(event.target.value), className: cn("w-full rounded-md border border-input bg-background text-foreground outline-none transition-colors hover:bg-accent/40 focus:ring-1 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background placeholder:text-muted-foreground/50", isPage ? "h-10 px-3 text-sm" : "h-8 px-2.5 text-[12px]") }) })) : null] })) : null, _jsxs("div", { className: "flex flex-wrap items-center gap-2 pt-0.5", children: [_jsx("button", { type: "submit", disabled: saving || Boolean(active.key && !apiKey.trim()), className: cn("inline-flex items-center justify-center gap-1.5 rounded-md bg-foreground font-medium text-background transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50", isPage ? "h-9 px-3 text-xs" : "h-8 px-3 text-[11px]"), children: saving ? (_jsxs(_Fragment, { children: [_jsx(IconLoader2, { size: isPage ? 14 : 11, className: "animate-spin" }), t("agentPanel.savingProvider", {
|
|
135
|
+
defaultValue: "Saving...",
|
|
136
|
+
})] })) : saved ? (_jsxs(_Fragment, { children: [_jsx(IconCheck, { size: isPage ? 14 : 11 }), t("agentPanel.providerSaved", {
|
|
137
|
+
defaultValue: "Connected",
|
|
138
|
+
})] })) : provider === "ollama" ? (t("agentPanel.useProvider", {
|
|
139
|
+
provider: active.label,
|
|
140
|
+
defaultValue: `Use ${active.label}`,
|
|
141
|
+
})) : (t("agentPanel.saveAndUseProvider", {
|
|
142
|
+
provider: active.label,
|
|
143
|
+
defaultValue: `Save and use ${active.label}`,
|
|
144
|
+
})) }), active.docsUrl ? (_jsxs("a", { href: active.docsUrl, target: "_blank", rel: "noopener noreferrer", className: "inline-flex items-center gap-1 rounded-md px-1.5 py-1 text-[10px] font-medium text-muted-foreground no-underline transition-colors hover:bg-accent/40 hover:text-foreground", children: [t("agentPanel.getApiKey", { defaultValue: "Get an API key" }), _jsx(IconExternalLink, { size: 11 })] })) : null] }), error ? (_jsx("p", { className: "text-[11px] leading-relaxed text-destructive", children: error })) : null] })] }));
|
|
145
|
+
}
|
|
@@ -6,8 +6,9 @@ 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 { saveAgentEngineProviderSettings } from "../agent-engine-key.js";
|
|
9
|
+
import { saveAgentEngineProviderSettings, setAgentEngineProvider, } from "../agent-engine-key.js";
|
|
10
10
|
import { AgentWorkspaceContent } from "../agent-page/AgentWorkspaceContent.js";
|
|
11
|
+
import { getAgentProviderOption, providerIdForEngine, } from "../agent-provider-catalog.js";
|
|
11
12
|
import { agentNativePath } from "../api-path.js";
|
|
12
13
|
import { BuilderBMark } from "../builder-mark.js";
|
|
13
14
|
import { Popover, PopoverContent, PopoverTrigger, } from "../components/ui/popover.js";
|
|
@@ -24,6 +25,7 @@ import { AgentsSection } from "./AgentsSection.js";
|
|
|
24
25
|
import { AutomationsSection } from "./AutomationsSection.js";
|
|
25
26
|
import { DemoModeSection } from "./DemoModeSection.js";
|
|
26
27
|
import { ExtensionsSettingsContent } from "./ExtensionsSettingsContent.js";
|
|
28
|
+
import { AgentProviderPicker } from "./ProviderSetupForm.js";
|
|
27
29
|
import { SecretsSection } from "./SecretsSection.js";
|
|
28
30
|
import { SettingsGroup, SettingsRow } from "./SettingsRow.js";
|
|
29
31
|
import { SettingsSection, SettingsSurfaceProvider, useSettingsSurface, } from "./SettingsSection.js";
|
|
@@ -343,8 +345,8 @@ function LLMSectionInner({ builderFlow, builderLoading, connectUrl, connected, o
|
|
|
343
345
|
const [baseUrlConfigured, setBaseUrlConfigured] = useState(false);
|
|
344
346
|
const [clearBaseUrl, setClearBaseUrl] = useState(false);
|
|
345
347
|
const [advancedOpen, setAdvancedOpen] = useState(false);
|
|
346
|
-
const [manualSetupOpen, setManualSetupOpen] = useState(false);
|
|
347
348
|
const [applyNote, setApplyNote] = useState(false);
|
|
349
|
+
const [applyError, setApplyError] = useState(null);
|
|
348
350
|
const [testing, setTesting] = useState(false);
|
|
349
351
|
const [testResult, setTestResult] = useState(null);
|
|
350
352
|
const [settingsStatus, setSettingsStatus] = useState(null);
|
|
@@ -420,32 +422,26 @@ function LLMSectionInner({ builderFlow, builderLoading, connectUrl, connected, o
|
|
|
420
422
|
envVar,
|
|
421
423
|
builderConnected,
|
|
422
424
|
});
|
|
423
|
-
const manualSetupHint =
|
|
424
|
-
? "Provide an OpenRouter key to use OpenRouter models like GLM 5.2."
|
|
425
|
-
: "Choose your AI provider and model.";
|
|
425
|
+
const manualSetupHint = "Select a provider.";
|
|
426
426
|
const engineChanged = selectedEngine !== currentEngine || selectedModel !== currentModel;
|
|
427
|
-
const
|
|
428
|
-
const
|
|
427
|
+
const selectedProvider = providerIdForEngine(selectedEngine) ?? "anthropic";
|
|
428
|
+
const selectedProviderOption = getAgentProviderOption(selectedProvider);
|
|
429
|
+
const isEndpointProvider = selectedProviderOption.supportsEndpoint === true;
|
|
430
|
+
const endpointChanged = isEndpointProvider && (!!baseUrl.trim() || clearBaseUrl);
|
|
429
431
|
const providerSettingsChanged = !!apiKey.trim() || endpointChanged;
|
|
430
|
-
// Hide the Anthropic-via-AI-SDK alias (redundant with the native entry)
|
|
431
|
-
// and Ollama (no API key to set here). The currently-selected engine is
|
|
432
|
-
// always kept so a stale setting doesn't vanish from the picker.
|
|
433
|
-
const providerOptions = engines
|
|
434
|
-
.filter((e) => e.name === selectedEngine ||
|
|
435
|
-
(e.name !== "ai-sdk:anthropic" && e.name !== "ai-sdk:ollama"))
|
|
436
|
-
.map((e) => ({ value: e.name, label: e.label }));
|
|
437
432
|
const modelOptions = latestModelsOnly(selectedEngineInfo?.supportedModels ?? []).map((m) => ({ value: m, label: friendlyModelName(m) }));
|
|
438
433
|
const handleSave = async () => {
|
|
439
|
-
if (!providerSettingsChanged || !envVar)
|
|
434
|
+
if (!providerSettingsChanged || (!envVar && !isEndpointProvider))
|
|
440
435
|
return;
|
|
441
436
|
setSaving(true);
|
|
442
437
|
try {
|
|
443
|
-
const nextBaseUrl =
|
|
438
|
+
const nextBaseUrl = isEndpointProvider ? baseUrl.trim() : "";
|
|
444
439
|
await saveAgentEngineProviderSettings({
|
|
445
|
-
|
|
440
|
+
provider: selectedProvider,
|
|
441
|
+
...(envVar ? { key: envVar } : {}),
|
|
446
442
|
...(apiKey.trim() ? { apiKey } : {}),
|
|
447
443
|
...(nextBaseUrl ? { baseUrl: nextBaseUrl } : {}),
|
|
448
|
-
...(
|
|
444
|
+
...(isEndpointProvider && clearBaseUrl ? { clearBaseUrl: true } : {}),
|
|
449
445
|
});
|
|
450
446
|
setSaved(true);
|
|
451
447
|
setApiKey("");
|
|
@@ -527,40 +523,46 @@ function LLMSectionInner({ builderFlow, builderLoading, connectUrl, connected, o
|
|
|
527
523
|
}
|
|
528
524
|
};
|
|
529
525
|
const handleApply = async () => {
|
|
526
|
+
setApplyError(null);
|
|
530
527
|
try {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
body: JSON.stringify({
|
|
535
|
-
action: "set",
|
|
536
|
-
engine: selectedEngine,
|
|
537
|
-
model: selectedModel,
|
|
538
|
-
}),
|
|
528
|
+
await setAgentEngineProvider({
|
|
529
|
+
provider: selectedProvider,
|
|
530
|
+
model: selectedModel,
|
|
539
531
|
});
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
532
|
+
setCurrentEngine(selectedEngine);
|
|
533
|
+
setCurrentModel(selectedModel);
|
|
534
|
+
setApplyNote(true);
|
|
535
|
+
refreshSettingsStatus();
|
|
536
|
+
notifyConfigChanged();
|
|
537
|
+
setTimeout(() => setApplyNote(false), 4000);
|
|
538
|
+
}
|
|
539
|
+
catch (err) {
|
|
540
|
+
setApplyError(err instanceof Error ? err.message : String(err));
|
|
548
541
|
}
|
|
549
|
-
catch { }
|
|
550
542
|
};
|
|
551
|
-
return (_jsx(SettingsSection, { id: settingsSectionDomId("llm"), icon: _jsx(IconBrain, { size: 14 }), title: "LLM",
|
|
543
|
+
return (_jsx(SettingsSection, { id: settingsSectionDomId("llm"), icon: _jsx(IconBrain, { size: 14 }), title: "LLM", required: true, connected: initialLoading ? undefined : anyKeyConfigured, subtitle: isPage
|
|
544
|
+
? undefined
|
|
545
|
+
: t("agentPanel.builderOrOwnKeys", {
|
|
546
|
+
defaultValue: "Choose Builder.io or custom keys.",
|
|
547
|
+
}), grouped: isPage && grouped, open: open, onToggle: onToggle, children: initialLoading ? (_jsx(SettingsLoadingRow, { controlCount: 2 })) : (_jsxs("div", { className: cn(isPage
|
|
552
548
|
? "flex items-center justify-between gap-4 px-5 py-4 sm:px-6"
|
|
553
|
-
: "
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
549
|
+
: "flex items-center justify-between gap-2"), children: [isPage && (_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-sm font-medium text-foreground", children: "AI provider" }), _jsx("p", { className: "mt-1 text-sm leading-6 text-muted-foreground", children: t("agentPanel.builderOrOwnKeys", {
|
|
550
|
+
defaultValue: "Choose Builder.io or custom keys.",
|
|
551
|
+
}) })] })), _jsxs("div", { className: cn("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: true }), _jsx(ManualSetupCard, { id: "llm-manual-setup", title: "Custom keys", hint: manualSetupHint, sourceBadge: builderConnected ? undefined : sourceBadge, bare: isPage, popover: true, popoverLabel: settingsConfigured
|
|
552
|
+
? "Manage"
|
|
553
|
+
: t("agentPanel.addOwnKeys", {
|
|
554
|
+
defaultValue: "Custom keys",
|
|
555
|
+
}), children: _jsxs("div", { className: "space-y-2 mb-1", children: [_jsx(AgentProviderPicker, { value: selectedProvider, layout: isPage ? "page" : "compact", onChange: (provider) => {
|
|
556
|
+
const option = getAgentProviderOption(provider);
|
|
557
|
+
setSelectedEngine(option.engine);
|
|
558
|
+
setSelectedModel(option.defaultModel);
|
|
559
559
|
setApiKey("");
|
|
560
560
|
setBaseUrl("");
|
|
561
561
|
setClearBaseUrl(false);
|
|
562
562
|
setAdvancedOpen(false);
|
|
563
|
-
} }), _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))) }))] }),
|
|
563
|
+
} }), _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))) }))] }), isEndpointProvider && (_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: selectedProvider === "ollama"
|
|
564
|
+
? "Local Ollama endpoint"
|
|
565
|
+
: "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) => {
|
|
564
566
|
setBaseUrl(e.target.value);
|
|
565
567
|
if (e.target.value.trim())
|
|
566
568
|
setClearBaseUrl(false);
|
|
@@ -569,14 +571,16 @@ function LLMSectionInner({ builderFlow, builderLoading, connectUrl, connected, o
|
|
|
569
571
|
handleSave();
|
|
570
572
|
}, placeholder: baseUrlConfigured
|
|
571
573
|
? "Leave blank to keep current endpoint"
|
|
572
|
-
:
|
|
574
|
+
: selectedProvider === "ollama"
|
|
575
|
+
? "http://localhost:11434"
|
|
576
|
+
: "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 }), baseUrlConfigured && (_jsxs("label", { className: "flex items-center gap-1.5 text-[10px] text-muted-foreground", children: [_jsx(Checkbox, { checked: clearBaseUrl, onChange: (checked) => {
|
|
573
577
|
setClearBaseUrl(checked);
|
|
574
578
|
if (checked)
|
|
575
579
|
setBaseUrl("");
|
|
576
|
-
}, "aria-label": "Clear saved endpoint override", className: "shrink-0" }), "Clear saved endpoint override"] })),
|
|
580
|
+
}, "aria-label": "Clear saved endpoint override", className: "shrink-0" }), "Clear saved endpoint override"] })), 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) => {
|
|
577
581
|
if (e.key === "Enter")
|
|
578
582
|
handleSave();
|
|
579
|
-
}, 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" }))] }) })
|
|
583
|
+
}, 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] })), applyError && (_jsxs("p", { className: cn("text-destructive", isPage ? "text-xs" : "text-[10px]"), children: ["Apply failed: ", applyError] })), applyNote && (_jsx("p", { className: cn("text-muted-foreground", isPage ? "text-xs" : "text-[10px]"), children: "Changes take effect on next conversation" }))] }) })] })] })) }));
|
|
580
584
|
}
|
|
581
585
|
function friendlyAppName(appId) {
|
|
582
586
|
return appId
|
|
@@ -587,7 +591,7 @@ function friendlyAppName(appId) {
|
|
|
587
591
|
}
|
|
588
592
|
function AppDefaultModelPicker({ engines, value, disabled, onChange, }) {
|
|
589
593
|
const [open, setOpen] = useState(false);
|
|
590
|
-
const visibleEngines = engines.filter((engine) => engine.name !== "ai-sdk:anthropic"
|
|
594
|
+
const visibleEngines = engines.filter((engine) => engine.name !== "ai-sdk:anthropic");
|
|
591
595
|
const selectedModel = value.includes("::")
|
|
592
596
|
? value.slice(value.indexOf("::") + 2)
|
|
593
597
|
: null;
|
|
@@ -664,8 +668,7 @@ function AppModelDefaultsSectionInner({ grouped = false, open, onToggle, }) {
|
|
|
664
668
|
useEffect(() => load(), [load]);
|
|
665
669
|
const selectedEngineInfo = settings?.engines.find((engine) => engine.name === selectedEngine) ?? null;
|
|
666
670
|
const engineOptions = (settings?.engines ?? [])
|
|
667
|
-
.filter((engine) => engine.name === selectedEngine ||
|
|
668
|
-
(engine.name !== "ai-sdk:anthropic" && engine.name !== "ai-sdk:ollama"))
|
|
671
|
+
.filter((engine) => engine.name === selectedEngine || engine.name !== "ai-sdk:anthropic")
|
|
669
672
|
.map((engine) => ({
|
|
670
673
|
value: engine.name,
|
|
671
674
|
label: engine.name === "builder"
|
|
@@ -8,3 +8,5 @@ export { SettingsGroup, SettingsRow, type SettingsGroupProps, type SettingsRowPr
|
|
|
8
8
|
export { SettingsSection, SettingsSurfaceProvider, useSettingsSurface, type SettingsSurface, } from "./SettingsSection.js";
|
|
9
9
|
export { SettingsLoadingRow, SettingsSkeleton, type SettingsLoadingRowProps, type SettingsSkeletonProps, } from "./SettingsSkeleton.js";
|
|
10
10
|
export { normalizeSettingsSection, settingsSectionDomId, useSettingsPanelController, type SettingsPanelController, type SettingsPanelControllerOptions, } from "./useSettingsPanelController.js";
|
|
11
|
+
export { AGENT_PROVIDER_CATALOG, getAgentProviderOption, providerIdForEngine, type AgentProviderId, type AgentProviderOption, } from "../agent-provider-catalog.js";
|
|
12
|
+
export { AgentProviderPicker, AgentProviderSetupForm, type AgentProviderPickerProps, type AgentProviderSetupFormProps, } from "./ProviderSetupForm.js";
|
|
@@ -8,3 +8,5 @@ export { SettingsGroup, SettingsRow, } from "./SettingsRow.js";
|
|
|
8
8
|
export { SettingsSection, SettingsSurfaceProvider, useSettingsSurface, } from "./SettingsSection.js";
|
|
9
9
|
export { SettingsLoadingRow, SettingsSkeleton, } from "./SettingsSkeleton.js";
|
|
10
10
|
export { normalizeSettingsSection, settingsSectionDomId, useSettingsPanelController, } from "./useSettingsPanelController.js";
|
|
11
|
+
export { AGENT_PROVIDER_CATALOG, getAgentProviderOption, providerIdForEngine, } from "../agent-provider-catalog.js";
|
|
12
|
+
export { AgentProviderPicker, AgentProviderSetupForm, } from "./ProviderSetupForm.js";
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
*/
|
|
31
31
|
import type { ActionRunContext } from "../action.js";
|
|
32
32
|
import type { ActionEntry } from "../agent/production-agent.js";
|
|
33
|
+
export type SandboxCodeMode = "run-code" | "tool-orchestration";
|
|
33
34
|
export interface RunCodeOptions {
|
|
34
35
|
/**
|
|
35
36
|
* Extra tool names (beyond the default set) that the sandbox bridge will
|
|
@@ -54,6 +55,10 @@ export interface ExecuteSandboxCodeOptions {
|
|
|
54
55
|
getActions: () => Record<string, ActionEntry>;
|
|
55
56
|
/** Extra bridge tool names beyond the defaults. */
|
|
56
57
|
extraBridgeTools?: Set<string>;
|
|
58
|
+
/** Host policy and helper surface to use inside the sandbox. */
|
|
59
|
+
mode?: SandboxCodeMode;
|
|
60
|
+
/** Maximum number of bridged child-tool calls for orchestration mode. */
|
|
61
|
+
maxToolCalls?: number;
|
|
57
62
|
/** Request context (owner/org) applied to bridged tool calls. */
|
|
58
63
|
context?: ActionRunContext;
|
|
59
64
|
}
|