@agent-native/core 0.185.0 → 0.186.0-nightly-20260923174435
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/calendar/actions/delete-event.ts +6 -4
- package/corpus/templates/calendar/actions/delete-events.ts +10 -11
- package/corpus/templates/calendar/actions/event-action-helpers.ts +53 -0
- package/corpus/templates/calendar/actions/get-event.ts +59 -14
- package/corpus/templates/calendar/actions/rsvp-event.ts +5 -3
- package/corpus/templates/calendar/actions/update-event.ts +15 -7
- package/corpus/templates/calendar/actions/update-events.ts +29 -11
- package/corpus/templates/calendar/changelog/2026-09-21-events-stay-editable-when-their-calendar-is-connected-throug.md +6 -0
- package/corpus/templates/calendar/server/lib/google-calendar.ts +70 -18
- package/corpus/templates/calendar/shared/google-calendar-sources.ts +47 -0
- package/corpus/templates/clips/actions/finalize-recording.ts +35 -1
- package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +5 -1
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +18 -1
- package/corpus/templates/clips/app/routes/_app.r.$recordingId.tsx +2 -2
- package/corpus/templates/clips/app/routes/record.tsx +1 -0
- package/corpus/templates/clips/changelog/2026-09-23-long-recording-menus-scroll-within-the-visible-space-so-ever.md +6 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +14 -4
- package/corpus/templates/content/app/blocks/contentBlockRegistry.tsx +9 -1
- package/corpus/templates/content/app/components/editor/SlashCommandMenu.tsx +16 -2
- package/corpus/templates/content/app/components/editor/registrySlashItems.ts +61 -40
- package/corpus/templates/content/app/i18n-data.ts +12 -0
- package/corpus/templates/content/app/routes/_app.settings.tsx +36 -9
- package/corpus/templates/content/docs/product/capabilities/content.renderer.custom-block.md +1 -1
- package/corpus/templates/content/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/content/shared/labs.ts +35 -1
- package/corpus/templates/slides/actions/get-design-system.ts +4 -2
- package/dist/agent/engine/openai-compatible-endpoint.d.ts +7 -0
- package/dist/agent/engine/openai-compatible-endpoint.js +9 -0
- package/dist/agent/engine/provider-endpoint-validation.d.ts +8 -1
- package/dist/agent/engine/provider-endpoint-validation.js +47 -10
- package/dist/agent/engine/registry.js +8 -5
- package/dist/automation/index.d.ts +1 -1
- package/dist/cli/skills.d.ts +3 -0
- package/dist/cli/skills.js +45 -9
- package/dist/client/agent-engine-key.d.ts +7 -0
- package/dist/client/agent-engine-key.js +37 -0
- package/dist/client/agent-provider-catalog.js +1 -1
- package/dist/client/settings/ProviderSetupForm.js +80 -7
- package/dist/client/settings/SettingsPanel.js +149 -11
- package/dist/client/use-chat-models.js +31 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/labs/actions/set-lab.js +1 -0
- package/dist/labs/registry.js +6 -1
- package/dist/localization/default-messages.d.ts +7 -1
- package/dist/localization/default-messages.js +7 -1
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/index.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +6 -6
- package/dist/provider-api/actions/provider-api.d.ts +3 -3
- package/dist/scripts/agent-engines/test-agent-engine.js +9 -7
- package/dist/secrets/routes.d.ts +3 -3
- package/dist/server/agent-engine-api-key-route.d.ts +3 -3
- package/dist/server/agent-engine-api-key-route.js +8 -5
- package/dist/server/agent-engine-ollama-models-route.d.ts +15 -0
- package/dist/server/agent-engine-ollama-models-route.js +105 -0
- package/dist/server/core-routes-plugin.js +5 -0
- package/dist/server/credential-provider.d.ts +13 -0
- package/dist/server/credential-provider.js +19 -0
- package/package.json +3 -3
|
@@ -2,13 +2,13 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { Checkbox, Picker, Skeleton, TextField, } from "@agent-native/toolkit/design-system";
|
|
3
3
|
import { Button as ToolkitButton } from "@agent-native/toolkit/ui/button";
|
|
4
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, IconPlugConnected, IconTopologyRing2, IconLoader2, IconUpload, IconCoin, IconMail, IconKey, IconMicrophone, IconEyeOff, IconBolt, IconGauge, IconApps, IconUsersGroup, IconTool, IconAlertCircle, } from "@tabler/icons-react";
|
|
5
|
+
import { IconChevronDown, IconChevronRight, IconCheck, IconExternalLink, IconBrain, IconHierarchy2, IconBrowser, IconGitBranch, IconCloud, IconDatabase, IconFolder, IconShield, IconPlugConnected, IconTopologyRing2, IconLoader2, IconUpload, IconCoin, IconMail, IconKey, IconMicrophone, IconEyeOff, IconBolt, IconGauge, IconApps, IconUsersGroup, IconTool, IconAlertCircle, IconSearch, } from "@tabler/icons-react";
|
|
6
6
|
import React, { Suspense, lazy, useState, useEffect, useCallback, useMemo, useRef, } from "react";
|
|
7
7
|
import { CHATGPT_SUBSCRIPTION_DEFAULT_MODEL, CHATGPT_SUBSCRIPTION_ENGINE_NAME, CHATGPT_SUBSCRIPTION_LAB_KEY, } from "../../agent/chatgpt-subscription-contract.js";
|
|
8
8
|
import { PROVIDER_ENV_PLACEHOLDERS } from "../../agent/engine/provider-env-vars.js";
|
|
9
9
|
import { buildSettingsRoute, STANDARD_APP_ROUTES, } from "../../navigation/index.js";
|
|
10
10
|
import { docsUrl } from "../../shared/docs-url.js";
|
|
11
|
-
import { saveAgentEngineProviderSettings, setAgentEngineProvider, } from "../agent-engine-key.js";
|
|
11
|
+
import { fetchOllamaModels, saveAgentEngineProviderSettings, setAgentEngineProvider, } from "../agent-engine-key.js";
|
|
12
12
|
import { AgentWorkspaceContent } from "../agent-page/AgentWorkspaceContent.js";
|
|
13
13
|
import { AGENT_PROVIDER_CATALOG, getAgentProviderOption, providerIdForEngine, } from "../agent-provider-catalog.js";
|
|
14
14
|
import { agentNativePath, appMountedPath } from "../api-path.js";
|
|
@@ -393,6 +393,9 @@ function LLMSectionInner({ builderFlow, builderLoading, builderStatusAvailable,
|
|
|
393
393
|
const [engineCatalogAvailable, setEngineCatalogAvailable] = useState(false);
|
|
394
394
|
const [statusProbeAvailable, setStatusProbeAvailable] = useState(false);
|
|
395
395
|
const probeGenerationRef = useRef({ env: 0, status: 0 });
|
|
396
|
+
const [ollamaModels, setOllamaModels] = useState(null);
|
|
397
|
+
const [ollamaModelsError, setOllamaModelsError] = useState(null);
|
|
398
|
+
const [ollamaModelsLoading, setOllamaModelsLoading] = useState(false);
|
|
396
399
|
const initialLoading = !enginesLoaded || !!builderLoading;
|
|
397
400
|
const refreshEnvKeys = useCallback(() => {
|
|
398
401
|
const generation = ++probeGenerationRef.current.env;
|
|
@@ -576,8 +579,47 @@ function LLMSectionInner({ builderFlow, builderLoading, builderStatusAvailable,
|
|
|
576
579
|
const manualSetupHint = "Select a provider.";
|
|
577
580
|
const engineChanged = selectedEngine !== currentEngine || selectedModel !== currentModel;
|
|
578
581
|
const isEndpointProvider = selectedProviderOption.supportsEndpoint === true;
|
|
582
|
+
const isOllama = selectedProvider === "ollama";
|
|
579
583
|
const endpointChanged = isEndpointProvider && (!!baseUrl.trim() || clearBaseUrl);
|
|
580
584
|
const providerSettingsChanged = !!apiKey.trim() || endpointChanged;
|
|
585
|
+
// Ask the Ollama server itself which models it has pulled, instead of only
|
|
586
|
+
// offering the static suggestion list. Triggered explicitly by the "Find
|
|
587
|
+
// models" button, mirroring the same flow in `AgentProviderSetupForm`.
|
|
588
|
+
const handleFindOllamaModels = () => {
|
|
589
|
+
setOllamaModelsLoading(true);
|
|
590
|
+
setOllamaModelsError(null);
|
|
591
|
+
const typedEndpoint = baseUrl.trim();
|
|
592
|
+
void fetchOllamaModels(typedEndpoint || undefined)
|
|
593
|
+
.then(async (models) => {
|
|
594
|
+
setOllamaModels(models);
|
|
595
|
+
setOllamaModelsError(null);
|
|
596
|
+
// A successful check is the only signal this address actually works;
|
|
597
|
+
// persist it immediately so other surfaces reading the saved Ollama
|
|
598
|
+
// endpoint (the chat composer's model picker) don't keep falling back
|
|
599
|
+
// to the localhost default until "Save" is also clicked.
|
|
600
|
+
if (typedEndpoint) {
|
|
601
|
+
try {
|
|
602
|
+
await saveAgentEngineProviderSettings({
|
|
603
|
+
provider: selectedProvider,
|
|
604
|
+
...(envVar ? { key: envVar } : {}),
|
|
605
|
+
baseUrl: typedEndpoint,
|
|
606
|
+
});
|
|
607
|
+
setBaseUrlConfigured(true);
|
|
608
|
+
}
|
|
609
|
+
catch {
|
|
610
|
+
// coercion-ok: the connectivity check itself still succeeded and
|
|
611
|
+
// the found models are shown; the address just wasn't persisted
|
|
612
|
+
// (e.g. a dropped session). The "Save endpoint" button below
|
|
613
|
+
// retries it, so this is never reported as a clean success.
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
})
|
|
617
|
+
.catch((err) => {
|
|
618
|
+
setOllamaModels(null);
|
|
619
|
+
setOllamaModelsError(err instanceof Error ? err.message : String(err));
|
|
620
|
+
})
|
|
621
|
+
.finally(() => setOllamaModelsLoading(false));
|
|
622
|
+
};
|
|
581
623
|
const modelOptions = (selectedEngineInfo?.supportedModels ?? []).map((m) => ({ value: m, label: friendlyModelName(m) }));
|
|
582
624
|
const handleSave = async () => {
|
|
583
625
|
if (!providerSettingsChanged || (!envVar && !isEndpointProvider))
|
|
@@ -735,7 +777,33 @@ function LLMSectionInner({ builderFlow, builderLoading, builderStatusAvailable,
|
|
|
735
777
|
setApplyError(null);
|
|
736
778
|
setApplyNote(false);
|
|
737
779
|
setTestResult(null);
|
|
738
|
-
|
|
780
|
+
setOllamaModels(null);
|
|
781
|
+
setOllamaModelsError(null);
|
|
782
|
+
} }), isOllama && isEndpointProvider ? (_jsxs("div", { className: "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" })] }), _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx("input", { type: "url", value: baseUrl, onChange: (e) => {
|
|
783
|
+
const baseUrl = e.target.value;
|
|
784
|
+
setSelectionState((previous) => ({
|
|
785
|
+
...previous,
|
|
786
|
+
baseUrl,
|
|
787
|
+
clearBaseUrl: baseUrl.trim()
|
|
788
|
+
? false
|
|
789
|
+
: previous.clearBaseUrl,
|
|
790
|
+
}));
|
|
791
|
+
setOllamaModels(null);
|
|
792
|
+
setOllamaModelsError(null);
|
|
793
|
+
}, onKeyDown: (e) => {
|
|
794
|
+
if (e.key === "Enter")
|
|
795
|
+
void handleSave();
|
|
796
|
+
}, placeholder: baseUrlConfigured
|
|
797
|
+
? "Leave blank to keep current endpoint"
|
|
798
|
+
: "http://localhost:11434 or local network address like http://192.168.1.123:11434", disabled: clearBaseUrl, spellCheck: false, autoComplete: "off", className: "flex h-9 min-w-0 flex-1 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 }), _jsxs(Button, { type: "button", intent: "neutral", emphasis: "outline", disabled: saving || ollamaModelsLoading || clearBaseUrl, onClick: handleFindOllamaModels, className: "inline-flex h-9 shrink-0 items-center gap-1.5 rounded-md border border-border bg-background px-2.5 text-[11px] font-medium text-foreground hover:bg-accent/40 disabled:cursor-not-allowed disabled:opacity-50", children: [ollamaModelsLoading ? (_jsx(IconLoader2, { size: 12, className: "animate-spin" })) : (_jsx(IconSearch, { size: 12 })), "Find models"] })] }), baseUrlConfigured && (_jsxs("label", { className: "flex items-center gap-1.5 text-[10px] text-muted-foreground", children: [_jsx(Checkbox, { checked: clearBaseUrl, onChange: (checked) => {
|
|
799
|
+
setSelectionState((previous) => ({
|
|
800
|
+
...previous,
|
|
801
|
+
clearBaseUrl: checked,
|
|
802
|
+
baseUrl: checked ? "" : previous.baseUrl,
|
|
803
|
+
}));
|
|
804
|
+
}, "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") }))] })) : null, _jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: fieldLabelClass(isPage), children: "Model" }), _jsx("input", { type: "text", list: isOllama
|
|
805
|
+
? undefined
|
|
806
|
+
: `model-suggestions-${selectedEngine}`, value: selectedModel, onChange: (e) => {
|
|
739
807
|
const model = e.target.value;
|
|
740
808
|
setSelectionState((previous) => ({
|
|
741
809
|
...previous,
|
|
@@ -744,9 +812,25 @@ function LLMSectionInner({ builderFlow, builderLoading, builderStatusAvailable,
|
|
|
744
812
|
setApplyError(null);
|
|
745
813
|
setApplyNote(false);
|
|
746
814
|
setTestResult(null);
|
|
747
|
-
}, 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))) }))
|
|
748
|
-
|
|
749
|
-
|
|
815
|
+
}, placeholder: selectedEngineInfo?.defaultModel ?? "e.g. model-id", spellCheck: false, autoComplete: "off", className: textInputClass(isPage), style: isPage ? CONTROL_STYLE_PAGE : CONTROL_STYLE }), !isOllama && modelOptions.length > 0 && (_jsx("datalist", { id: `model-suggestions-${selectedEngine}`, children: modelOptions.map((opt) => (_jsx("option", { value: opt.value, label: opt.label }, opt.value))) })), isOllama ? (_jsxs("div", { className: "space-y-1.5", children: [ollamaModels && ollamaModels.length > 0 ? (_jsx("div", { className: "flex flex-wrap gap-1.5", children: ollamaModels.map((modelOption) => (_jsx(Button, { type: "button", disabled: saving, onClick: () => {
|
|
816
|
+
setSelectionState((previous) => ({
|
|
817
|
+
...previous,
|
|
818
|
+
selectedModel: modelOption,
|
|
819
|
+
}));
|
|
820
|
+
setApplyError(null);
|
|
821
|
+
setApplyNote(false);
|
|
822
|
+
setTestResult(null);
|
|
823
|
+
}, "aria-pressed": selectedModel === modelOption, className: cn("rounded-md border px-2 py-1 text-[11px] font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50", selectedModel === modelOption
|
|
824
|
+
? "border-primary bg-primary/10 text-primary"
|
|
825
|
+
: "border-border bg-background text-foreground hover:bg-accent/40"), children: modelOption }, modelOption))) })) : null, _jsx("p", { className: "text-[10px] leading-relaxed text-muted-foreground", children: ollamaModelsLoading
|
|
826
|
+
? "Checking installed models…"
|
|
827
|
+
: ollamaModels && ollamaModels.length > 0
|
|
828
|
+
? `Found ${ollamaModels.length} installed model${ollamaModels.length === 1 ? "" : "s"}.`
|
|
829
|
+
: ollamaModels
|
|
830
|
+
? "Connected, but no models are pulled yet — run `ollama pull llama3.1`."
|
|
831
|
+
: ollamaModelsError
|
|
832
|
+
? `${ollamaModelsError} Showing example model names below.`
|
|
833
|
+
: 'Click "Find models" above to list what your Ollama server actually has installed.' })] })) : null] }), !isOllama && 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: "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) => {
|
|
750
834
|
const baseUrl = e.target.value;
|
|
751
835
|
setSelectionState((previous) => ({
|
|
752
836
|
...previous,
|
|
@@ -760,9 +844,7 @@ function LLMSectionInner({ builderFlow, builderLoading, builderStatusAvailable,
|
|
|
760
844
|
void handleSave();
|
|
761
845
|
}, placeholder: baseUrlConfigured
|
|
762
846
|
? "Leave blank to keep current endpoint"
|
|
763
|
-
:
|
|
764
|
-
? "http://localhost:11434"
|
|
765
|
-
: "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) => {
|
|
847
|
+
: "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) => {
|
|
766
848
|
setSelectionState((previous) => ({
|
|
767
849
|
...previous,
|
|
768
850
|
clearBaseUrl: checked,
|
|
@@ -793,7 +875,34 @@ function friendlyAppName(appId) {
|
|
|
793
875
|
}
|
|
794
876
|
function AppDefaultModelPicker({ engines, value, disabled, onChange, }) {
|
|
795
877
|
const [open, setOpen] = useState(false);
|
|
878
|
+
const [ollamaModels, setOllamaModels] = useState(null);
|
|
796
879
|
const visibleEngines = engines.filter((engine) => engine.name !== "ai-sdk:anthropic");
|
|
880
|
+
// The static catalog only has the curated suggestion models for Ollama.
|
|
881
|
+
// Ask the configured Ollama server what it actually has installed and
|
|
882
|
+
// swap those in — a second, later render, so it never blocks this
|
|
883
|
+
// picker's first paint on a local network round trip. Gated on the
|
|
884
|
+
// popover actually being opened (a deliberate user action), not merely
|
|
885
|
+
// Ollama's presence in the catalog, which it always has by default —
|
|
886
|
+
// an unconditional probe would 502 for the vast majority of setups that
|
|
887
|
+
// never touched Ollama and never even open this picker.
|
|
888
|
+
useEffect(() => {
|
|
889
|
+
if (!open)
|
|
890
|
+
return;
|
|
891
|
+
if (!engines.some((engine) => engine.name === "ai-sdk:ollama"))
|
|
892
|
+
return;
|
|
893
|
+
let cancelled = false;
|
|
894
|
+
void fetchOllamaModels()
|
|
895
|
+
.then((models) => {
|
|
896
|
+
if (!cancelled && models.length > 0)
|
|
897
|
+
setOllamaModels(models);
|
|
898
|
+
})
|
|
899
|
+
.catch(() => {
|
|
900
|
+
// No local Ollama server reachable — keep the static suggestions.
|
|
901
|
+
});
|
|
902
|
+
return () => {
|
|
903
|
+
cancelled = true;
|
|
904
|
+
};
|
|
905
|
+
}, [open, engines]);
|
|
797
906
|
const selectedModel = value.includes("::")
|
|
798
907
|
? value.slice(value.indexOf("::") + 2)
|
|
799
908
|
: null;
|
|
@@ -817,7 +926,9 @@ function AppDefaultModelPicker({ engines, value, disabled, onChange, }) {
|
|
|
817
926
|
const providerLabel = engine.name === "builder"
|
|
818
927
|
? "Builder.io"
|
|
819
928
|
: engine.label || engine.name;
|
|
820
|
-
const modelIds =
|
|
929
|
+
const modelIds = engine.name === "ai-sdk:ollama" && ollamaModels?.length
|
|
930
|
+
? ollamaModels
|
|
931
|
+
: latestModelsOnly(engine.supportedModels);
|
|
821
932
|
const models = modelIds.length
|
|
822
933
|
? modelIds
|
|
823
934
|
: engine.defaultModel
|
|
@@ -842,6 +953,7 @@ function AppModelDefaultsSectionInner({ grouped = false, open, onToggle, }) {
|
|
|
842
953
|
const [saving, setSaving] = useState(false);
|
|
843
954
|
const [saved, setSaved] = useState(false);
|
|
844
955
|
const [error, setError] = useState(null);
|
|
956
|
+
const [ollamaModels, setOllamaModels] = useState(null);
|
|
845
957
|
const load = useCallback(() => {
|
|
846
958
|
let cancelled = false;
|
|
847
959
|
setLoading(true);
|
|
@@ -868,9 +980,35 @@ function AppModelDefaultsSectionInner({ grouped = false, open, onToggle, }) {
|
|
|
868
980
|
};
|
|
869
981
|
}, []);
|
|
870
982
|
useEffect(() => load(), [load]);
|
|
983
|
+
// The static catalog only has the curated suggestion models for Ollama.
|
|
984
|
+
// Ask the configured Ollama server what it actually has installed and
|
|
985
|
+
// swap those in — a second, later render, so it never blocks this
|
|
986
|
+
// section's first paint on a local network round trip. Gated on Ollama
|
|
987
|
+
// actually being the selected engine here (not merely present in the
|
|
988
|
+
// catalog, which it always is by default) — an unconditional probe would
|
|
989
|
+
// 502 for the vast majority of setups that never touched Ollama.
|
|
990
|
+
useEffect(() => {
|
|
991
|
+
if (selectedEngine !== "ai-sdk:ollama")
|
|
992
|
+
return;
|
|
993
|
+
let cancelled = false;
|
|
994
|
+
void fetchOllamaModels()
|
|
995
|
+
.then((models) => {
|
|
996
|
+
if (!cancelled && models.length > 0)
|
|
997
|
+
setOllamaModels(models);
|
|
998
|
+
})
|
|
999
|
+
.catch(() => {
|
|
1000
|
+
// No local Ollama server reachable — keep the static suggestions.
|
|
1001
|
+
});
|
|
1002
|
+
return () => {
|
|
1003
|
+
cancelled = true;
|
|
1004
|
+
};
|
|
1005
|
+
}, [selectedEngine]);
|
|
871
1006
|
if (!loading && !settings)
|
|
872
1007
|
return null;
|
|
873
1008
|
const selectedEngineInfo = settings?.engines.find((engine) => engine.name === selectedEngine) ?? null;
|
|
1009
|
+
const selectedEngineModels = selectedEngine === "ai-sdk:ollama" && ollamaModels?.length
|
|
1010
|
+
? ollamaModels
|
|
1011
|
+
: (selectedEngineInfo?.supportedModels ?? []);
|
|
874
1012
|
const engineOptions = (settings?.engines ?? [])
|
|
875
1013
|
.filter((engine) => engine.name === selectedEngine || engine.name !== "ai-sdk:anthropic")
|
|
876
1014
|
.map((engine) => ({
|
|
@@ -990,7 +1128,7 @@ function AppModelDefaultsSectionInner({ grouped = false, open, onToggle, }) {
|
|
|
990
1128
|
const info = settings.engines.find((engine) => engine.name === value);
|
|
991
1129
|
setSelectedModel(info?.defaultModel ?? "");
|
|
992
1130
|
setError(null);
|
|
993
|
-
} }), _jsx(AppDefaultModelField, { engine: selectedEngine, models:
|
|
1131
|
+
} }), _jsx(AppDefaultModelField, { engine: selectedEngine, models: selectedEngineModels, value: selectedModel, defaultModel: selectedEngineInfo?.defaultModel, disabled: !settings.canUpdate || saving, onValueChange: (value) => {
|
|
994
1132
|
setSelectedModel(value);
|
|
995
1133
|
setError(null);
|
|
996
1134
|
}, onEnter: () => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
2
|
import { DEFAULT_MODEL } from "../agent/default-model.js";
|
|
3
3
|
import { DEFAULT_REASONING_EFFORT, getReasoningEffortOptionsForModel, resolveReasoningEffortSelection, } from "../shared/reasoning-effort.js";
|
|
4
|
+
import { fetchOllamaModels } from "./agent-engine-key.js";
|
|
4
5
|
import { buildChatModelGroups, } from "./chat-model-groups.js";
|
|
5
6
|
import { fetchBuilderStatus, fetchEnvironmentStatus, } from "./client-status-requests.js";
|
|
6
7
|
import { callAction } from "./use-action.js";
|
|
@@ -201,6 +202,36 @@ export function useChatModels({ storageKey = DEFAULT_STORAGE_KEY, enabled = true
|
|
|
201
202
|
const nextDefaultModel = currentModel ?? DEFAULT_MODEL;
|
|
202
203
|
setAvailableModels(groups);
|
|
203
204
|
setDefaultModel(nextDefaultModel);
|
|
205
|
+
// The static catalog only has the curated suggestion models for
|
|
206
|
+
// Ollama. Once the engine list is in, ask the configured Ollama
|
|
207
|
+
// server what it actually has installed and swap those in — a
|
|
208
|
+
// second, later render, so it never blocks the picker's first
|
|
209
|
+
// paint on a local network round trip. Gated on Ollama actually
|
|
210
|
+
// being the current engine (not merely present in the catalog,
|
|
211
|
+
// which it always is): every app registers it by default, so an
|
|
212
|
+
// unconditional probe would 502 on every chat load for the vast
|
|
213
|
+
// majority of setups that never touched Ollama.
|
|
214
|
+
if (currentEngineName === "ai-sdk:ollama") {
|
|
215
|
+
void fetchOllamaModels()
|
|
216
|
+
.then((liveModels) => {
|
|
217
|
+
if (!isCurrentRefresh() || liveModels.length === 0)
|
|
218
|
+
return;
|
|
219
|
+
const liveEngines = enginesData.engines.map((engine) => engine.name === "ai-sdk:ollama"
|
|
220
|
+
? { ...engine, supportedModels: liveModels }
|
|
221
|
+
: engine);
|
|
222
|
+
setAvailableModels(buildChatModelGroups({
|
|
223
|
+
engines: liveEngines,
|
|
224
|
+
configuredKeys,
|
|
225
|
+
builderConnected,
|
|
226
|
+
currentEngineName,
|
|
227
|
+
currentModel,
|
|
228
|
+
}));
|
|
229
|
+
})
|
|
230
|
+
.catch(() => {
|
|
231
|
+
// No local Ollama server reachable — keep the static
|
|
232
|
+
// suggestion list already rendered above.
|
|
233
|
+
});
|
|
234
|
+
}
|
|
204
235
|
const selection = selectionRef.current;
|
|
205
236
|
// Default only to a CONFIGURED group, and to nothing when there is
|
|
206
237
|
// none. `DEFAULT_MODEL` is a builder-gateway id that no group carries
|
|
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
62
62
|
error: string;
|
|
63
63
|
states?: undefined;
|
|
64
64
|
} | {
|
|
65
|
+
error?: undefined;
|
|
65
66
|
states: {
|
|
66
67
|
clientId: number;
|
|
67
68
|
state: string;
|
|
68
69
|
}[];
|
|
69
|
-
error?: undefined;
|
|
70
70
|
}>>;
|
|
71
71
|
/**
|
|
72
72
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
77
77
|
error: string;
|
|
78
78
|
users?: undefined;
|
|
79
79
|
} | {
|
|
80
|
+
error?: undefined;
|
|
80
81
|
users: {
|
|
81
82
|
clientId: number;
|
|
82
83
|
lastSeen: number;
|
|
83
84
|
}[];
|
|
84
|
-
error?: undefined;
|
|
85
85
|
}>>;
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
26
26
|
* Body: { update: string (base64), requestSource?: string }
|
|
27
27
|
*/
|
|
28
28
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
ok?: undefined;
|
|
30
29
|
error: string;
|
|
30
|
+
ok?: undefined;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
|
@@ -9,6 +9,7 @@ const schema = z.object({
|
|
|
9
9
|
export default defineAction({
|
|
10
10
|
description: "Opt the current user into or out of one registered lab. Unset preferences use the app-defined default; labs may expose new or unstable features.",
|
|
11
11
|
schema,
|
|
12
|
+
http: { method: "POST" },
|
|
12
13
|
run: async (args, ctx) => {
|
|
13
14
|
const email = ctx?.userEmail;
|
|
14
15
|
if (!email)
|
package/dist/labs/registry.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
const
|
|
1
|
+
const LABS_REGISTRY_SYMBOL = Symbol.for("agent-native.labs.registry");
|
|
2
|
+
const globalLabsRegistry = globalThis;
|
|
3
|
+
// Dev servers can load app plugins from source while action registries resolve
|
|
4
|
+
// the built package. Keep both module instances on one process-wide registry.
|
|
5
|
+
const registry = globalLabsRegistry[LABS_REGISTRY_SYMBOL] ??
|
|
6
|
+
(globalLabsRegistry[LABS_REGISTRY_SYMBOL] = new Map());
|
|
2
7
|
function normalizeDefinition(definition) {
|
|
3
8
|
const key = definition.key.trim();
|
|
4
9
|
if (!/^[A-Za-z][A-Za-z0-9._-]{0,63}$/.test(key)) {
|
|
@@ -643,8 +643,14 @@ declare const messages: {
|
|
|
643
643
|
modelId: string;
|
|
644
644
|
endpointUrl: string;
|
|
645
645
|
optional: string;
|
|
646
|
-
ollamaEndpointHint: string;
|
|
647
646
|
compatibleEndpointHint: string;
|
|
647
|
+
findModels: string;
|
|
648
|
+
ollamaModelsChecking: string;
|
|
649
|
+
ollamaModelsFound_one: string;
|
|
650
|
+
ollamaModelsFound_other: string;
|
|
651
|
+
ollamaModelsNone: string;
|
|
652
|
+
ollamaModelsError: string;
|
|
653
|
+
ollamaModelsPrompt: string;
|
|
648
654
|
savingProvider: string;
|
|
649
655
|
providerSaved: string;
|
|
650
656
|
useProvider: string;
|
|
@@ -650,8 +650,14 @@ const messages = {
|
|
|
650
650
|
modelId: "Model ID",
|
|
651
651
|
endpointUrl: "Endpoint URL",
|
|
652
652
|
optional: "Optional",
|
|
653
|
-
ollamaEndpointHint: "Defaults to Ollama at http://localhost:11434.",
|
|
654
653
|
compatibleEndpointHint: "Use this for LiteLLM or another OpenAI-compatible gateway.",
|
|
654
|
+
findModels: "Find models",
|
|
655
|
+
ollamaModelsChecking: "Checking installed models…",
|
|
656
|
+
ollamaModelsFound_one: "Found {{count}} installed model.",
|
|
657
|
+
ollamaModelsFound_other: "Found {{count}} installed models.",
|
|
658
|
+
ollamaModelsNone: "Connected, but no models are pulled yet — run `ollama pull llama3.1`.",
|
|
659
|
+
ollamaModelsError: "{{error}} Showing example model names below.",
|
|
660
|
+
ollamaModelsPrompt: 'Click "Find models" above to list what your Ollama server actually has installed.',
|
|
655
661
|
savingProvider: "Saving...",
|
|
656
662
|
providerSaved: "Connected",
|
|
657
663
|
useProvider: "Use {{provider}}",
|
|
@@ -137,13 +137,13 @@ export declare function screenMemoryMcpToolDefinitions(): ({
|
|
|
137
137
|
inputSchema: {
|
|
138
138
|
type: string;
|
|
139
139
|
properties: {
|
|
140
|
+
count?: undefined;
|
|
140
141
|
query?: undefined;
|
|
141
142
|
minutes?: undefined;
|
|
142
143
|
limit?: undefined;
|
|
143
144
|
clientHint?: undefined;
|
|
144
145
|
timestamp?: undefined;
|
|
145
146
|
chapterId?: undefined;
|
|
146
|
-
count?: undefined;
|
|
147
147
|
startAt?: undefined;
|
|
148
148
|
endAt?: undefined;
|
|
149
149
|
reason?: undefined;
|
|
@@ -159,6 +159,7 @@ export declare function screenMemoryMcpToolDefinitions(): ({
|
|
|
159
159
|
inputSchema: {
|
|
160
160
|
type: string;
|
|
161
161
|
properties: {
|
|
162
|
+
count?: undefined;
|
|
162
163
|
query: {
|
|
163
164
|
type: string;
|
|
164
165
|
description: string;
|
|
@@ -174,7 +175,6 @@ export declare function screenMemoryMcpToolDefinitions(): ({
|
|
|
174
175
|
clientHint?: undefined;
|
|
175
176
|
timestamp?: undefined;
|
|
176
177
|
chapterId?: undefined;
|
|
177
|
-
count?: undefined;
|
|
178
178
|
startAt?: undefined;
|
|
179
179
|
endAt?: undefined;
|
|
180
180
|
reason?: undefined;
|
|
@@ -190,6 +190,7 @@ export declare function screenMemoryMcpToolDefinitions(): ({
|
|
|
190
190
|
inputSchema: {
|
|
191
191
|
type: string;
|
|
192
192
|
properties: {
|
|
193
|
+
count?: undefined;
|
|
193
194
|
minutes: {
|
|
194
195
|
type: string;
|
|
195
196
|
description: string;
|
|
@@ -199,7 +200,6 @@ export declare function screenMemoryMcpToolDefinitions(): ({
|
|
|
199
200
|
clientHint?: undefined;
|
|
200
201
|
timestamp?: undefined;
|
|
201
202
|
chapterId?: undefined;
|
|
202
|
-
count?: undefined;
|
|
203
203
|
startAt?: undefined;
|
|
204
204
|
endAt?: undefined;
|
|
205
205
|
reason?: undefined;
|
|
@@ -216,6 +216,7 @@ export declare function screenMemoryMcpToolDefinitions(): ({
|
|
|
216
216
|
type: string;
|
|
217
217
|
required: string[];
|
|
218
218
|
properties: {
|
|
219
|
+
count?: undefined;
|
|
219
220
|
query: {
|
|
220
221
|
type: string;
|
|
221
222
|
description: string;
|
|
@@ -234,7 +235,6 @@ export declare function screenMemoryMcpToolDefinitions(): ({
|
|
|
234
235
|
};
|
|
235
236
|
timestamp?: undefined;
|
|
236
237
|
chapterId?: undefined;
|
|
237
|
-
count?: undefined;
|
|
238
238
|
startAt?: undefined;
|
|
239
239
|
endAt?: undefined;
|
|
240
240
|
reason?: undefined;
|
|
@@ -250,6 +250,7 @@ export declare function screenMemoryMcpToolDefinitions(): ({
|
|
|
250
250
|
type: string;
|
|
251
251
|
required: string[];
|
|
252
252
|
properties: {
|
|
253
|
+
count?: undefined;
|
|
253
254
|
query?: undefined;
|
|
254
255
|
minutes?: undefined;
|
|
255
256
|
limit?: undefined;
|
|
@@ -263,7 +264,6 @@ export declare function screenMemoryMcpToolDefinitions(): ({
|
|
|
263
264
|
description: string;
|
|
264
265
|
};
|
|
265
266
|
chapterId?: undefined;
|
|
266
|
-
count?: undefined;
|
|
267
267
|
startAt?: undefined;
|
|
268
268
|
endAt?: undefined;
|
|
269
269
|
includeMicrophone?: undefined;
|
|
@@ -314,13 +314,13 @@ export declare function screenMemoryMcpToolDefinitions(): ({
|
|
|
314
314
|
type: string;
|
|
315
315
|
required: string[];
|
|
316
316
|
properties: {
|
|
317
|
+
count?: undefined;
|
|
317
318
|
query?: undefined;
|
|
318
319
|
minutes?: undefined;
|
|
319
320
|
limit?: undefined;
|
|
320
321
|
clientHint?: undefined;
|
|
321
322
|
timestamp?: undefined;
|
|
322
323
|
chapterId?: undefined;
|
|
323
|
-
count?: undefined;
|
|
324
324
|
startAt: {
|
|
325
325
|
type: string;
|
|
326
326
|
description: string;
|
|
@@ -349,13 +349,13 @@ export declare function screenMemoryMcpToolDefinitions(): ({
|
|
|
349
349
|
type: string;
|
|
350
350
|
required: string[];
|
|
351
351
|
properties: {
|
|
352
|
+
count?: undefined;
|
|
352
353
|
query?: undefined;
|
|
353
354
|
minutes?: undefined;
|
|
354
355
|
limit?: undefined;
|
|
355
356
|
clientHint?: undefined;
|
|
356
357
|
timestamp?: undefined;
|
|
357
358
|
chapterId?: undefined;
|
|
358
|
-
count?: undefined;
|
|
359
359
|
startAt?: undefined;
|
|
360
360
|
endAt?: undefined;
|
|
361
361
|
reason?: undefined;
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
* DELETE /_agent-native/notifications/:id — delete
|
|
12
12
|
*/
|
|
13
13
|
export declare function createNotificationsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<"" | import("./types.js").Notification[] | {
|
|
14
|
+
error?: undefined;
|
|
14
15
|
count: number;
|
|
15
16
|
updated?: undefined;
|
|
16
|
-
error?: undefined;
|
|
17
17
|
ok?: undefined;
|
|
18
18
|
} | {
|
|
19
|
+
error?: undefined;
|
|
19
20
|
count?: undefined;
|
|
20
21
|
updated: number;
|
|
21
|
-
error?: undefined;
|
|
22
22
|
ok?: undefined;
|
|
23
23
|
} | {
|
|
24
24
|
count?: undefined;
|
|
@@ -26,8 +26,8 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
|
|
|
26
26
|
error: string;
|
|
27
27
|
ok?: undefined;
|
|
28
28
|
} | {
|
|
29
|
+
error?: undefined;
|
|
29
30
|
count?: undefined;
|
|
30
31
|
updated?: undefined;
|
|
31
|
-
error?: undefined;
|
|
32
32
|
ok: boolean;
|
|
33
33
|
}>>;
|
|
@@ -41,11 +41,11 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
41
41
|
thumbsUpRate: number;
|
|
42
42
|
avgEvalScore: number;
|
|
43
43
|
} | {
|
|
44
|
+
id?: undefined;
|
|
44
45
|
error?: undefined;
|
|
45
46
|
ok?: undefined;
|
|
46
47
|
summary: import("./types.js").TraceSummary;
|
|
47
48
|
spans: import("./types.js").TraceSpan[];
|
|
48
|
-
id?: undefined;
|
|
49
49
|
} | {
|
|
50
50
|
error?: undefined;
|
|
51
51
|
ok?: undefined;
|
|
@@ -53,15 +53,15 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
53
53
|
spans?: undefined;
|
|
54
54
|
id: string;
|
|
55
55
|
} | {
|
|
56
|
+
id?: undefined;
|
|
56
57
|
ok?: undefined;
|
|
57
58
|
summary?: undefined;
|
|
58
59
|
spans?: undefined;
|
|
59
|
-
id?: undefined;
|
|
60
60
|
error: any;
|
|
61
61
|
} | {
|
|
62
|
+
id?: undefined;
|
|
62
63
|
error?: undefined;
|
|
63
64
|
summary?: undefined;
|
|
64
65
|
spans?: undefined;
|
|
65
|
-
id?: undefined;
|
|
66
66
|
ok: boolean;
|
|
67
67
|
}>>;
|
package/dist/org/index.d.ts
CHANGED
|
@@ -136,8 +136,8 @@ export declare const getMyOrgHandler: import("h3").EventHandlerWithFetch<import(
|
|
|
136
136
|
export declare const createOrgHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
137
137
|
name?: undefined;
|
|
138
138
|
success: boolean;
|
|
139
|
-
id?: undefined;
|
|
140
139
|
role?: undefined;
|
|
140
|
+
id?: undefined;
|
|
141
141
|
} | {
|
|
142
142
|
success?: undefined;
|
|
143
143
|
id: string;
|
|
@@ -75,8 +75,8 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
75
75
|
user: "user";
|
|
76
76
|
}>>;
|
|
77
77
|
}, z.core.$strip>>, {
|
|
78
|
-
id?: undefined;
|
|
79
78
|
message?: undefined;
|
|
79
|
+
id?: undefined;
|
|
80
80
|
deleted?: undefined;
|
|
81
81
|
providers: {
|
|
82
82
|
id: string;
|
|
@@ -93,20 +93,20 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
93
93
|
registered?: undefined;
|
|
94
94
|
label?: undefined;
|
|
95
95
|
} | {
|
|
96
|
-
id?: undefined;
|
|
97
96
|
message?: undefined;
|
|
98
|
-
|
|
97
|
+
id?: undefined;
|
|
99
98
|
deleted?: undefined;
|
|
100
99
|
providers?: undefined;
|
|
100
|
+
count?: undefined;
|
|
101
101
|
found: boolean;
|
|
102
102
|
provider: import("../custom-registry.js").CustomProviderConfig;
|
|
103
103
|
registered?: undefined;
|
|
104
104
|
label?: undefined;
|
|
105
105
|
} | {
|
|
106
106
|
message?: undefined;
|
|
107
|
-
count?: undefined;
|
|
108
107
|
deleted?: undefined;
|
|
109
108
|
providers?: undefined;
|
|
109
|
+
count?: undefined;
|
|
110
110
|
provider?: undefined;
|
|
111
111
|
found: boolean;
|
|
112
112
|
id: string;
|
|
@@ -114,8 +114,8 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
114
114
|
label?: undefined;
|
|
115
115
|
} | {
|
|
116
116
|
message?: undefined;
|
|
117
|
-
count?: undefined;
|
|
118
117
|
providers?: undefined;
|
|
118
|
+
count?: undefined;
|
|
119
119
|
provider?: undefined;
|
|
120
120
|
found?: undefined;
|
|
121
121
|
deleted: boolean;
|
|
@@ -123,9 +123,9 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
123
123
|
registered?: undefined;
|
|
124
124
|
label?: undefined;
|
|
125
125
|
} | {
|
|
126
|
-
count?: undefined;
|
|
127
126
|
deleted?: undefined;
|
|
128
127
|
providers?: undefined;
|
|
128
|
+
count?: undefined;
|
|
129
129
|
provider?: undefined;
|
|
130
130
|
found?: undefined;
|
|
131
131
|
registered: boolean;
|