feat: Size ollama listing, Help button

This commit is contained in:
shiva raj badu 2026-04-13 21:25:08 +05:45
parent adcda8676d
commit b0e610ca07
No known key found for this signature in database
3 changed files with 94 additions and 28 deletions

View file

@ -1,7 +1,7 @@
"use client";
import React from "react";
import { LayoutDashboard, Star, Brain, Settings, Palette } from "lucide-react";
import { LayoutDashboard, Star, Brain, Settings, Palette, HelpCircle } from "lucide-react";
import { usePathname } from "next/navigation";
import Link from "next/link";
import { useRouter } from "next/navigation";
@ -105,11 +105,16 @@ const DashboardSidebar = () => {
<div className=" pt-5 border-t border-[#E1E1E5] font-syne "
>
<div className="mb-4">
<Link href="https://docs.presenton.ai/help" target="_blank" className="flex flex-col tex-center items-center gap-2 transition-colors"><HelpCircle className="w-4 h-4" /><span className="text-[11px] text-slate-800">Help</span></Link>
</div>
<div className="mb-4">
<Link href="https://discord.com/invite/9ZsKKxudNE" target="_blank" className="flex flex-col tex-center items-center gap-2 transition-colors"><img src="/discord.png" alt="Discord" className="w-5 h-5 rounded-full object-cover border border-[#EDEEEF]" /><span className="text-[11px] text-slate-800">Community</span></Link>
</div>
{BelongingNavItems.map(({ key, label: itemLabel, icon: Icon }) => {
const isActive = activeTab === key;
return (

View file

@ -17,6 +17,13 @@ interface OpenAIConfigProps {
onInputChange: (value: string | boolean, field: string) => void;
llmConfig: LLMConfig;
}
interface ModelOption {
value: string;
label: string;
size?: string;
}
const TextProvider = ({
onInputChange,
@ -26,7 +33,7 @@ const TextProvider = ({
) => {
const [openProviderSelect, setOpenProviderSelect] = useState(false);
const [openModelSelect, setOpenModelSelect] = useState(false);
const [availableModels, setAvailableModels] = useState<string[]>([]);
const [availableModels, setAvailableModels] = useState<ModelOption[]>([]);
const [modelsLoading, setModelsLoading] = useState(false);
const [modelsChecked, setModelsChecked] = useState(false);
const [showApiKey, setShowApiKey] = useState(false);
@ -157,19 +164,48 @@ const TextProvider = ({
if (response.ok) {
const data = await response.json();
const normalizedModels: string[] = selectedProvider === 'ollama'
const normalizedModels: ModelOption[] = selectedProvider === 'ollama'
? Array.isArray(data)
? data.map((model: { value?: string; label?: string }) => model.value || model.label || '').filter(Boolean)
? data
.map((model) => {
if (typeof model === 'string') {
return {
value: model,
label: model,
};
}
if (model && typeof model === 'object') {
const typedModel = model as { value?: string; label?: string; size?: string };
return {
value: typedModel.value || typedModel.label || '',
label: typedModel.label || typedModel.value || '',
size: typedModel.size,
};
}
return {
value: '',
label: '',
};
})
.filter((model: ModelOption) => Boolean(model.value))
: []
: Array.isArray(data)
? data
.filter((model): model is string => typeof model === 'string')
.map((model) => ({
value: model,
label: model,
}))
: [];
setAvailableModels(normalizedModels);
setModelsChecked(true);
if (normalizedModels.length > 0 && currentModelField) {
if (currentModel && normalizedModels.includes(currentModel)) {
const modelValues = normalizedModels.map((model) => model.value);
if (currentModel && modelValues.includes(currentModel)) {
onInputChange(currentModel, currentModelField);
return;
}
@ -181,9 +217,9 @@ const TextProvider = ({
? 'models/gemini-2.5-flash'
: selectedProvider === 'anthropic'
? 'claude-sonnet-4-20250514'
: normalizedModels[0];
: modelValues[0];
const nextModel = normalizedModels.includes(preferredDefault) ? preferredDefault : normalizedModels[0];
const nextModel = modelValues.includes(preferredDefault) ? preferredDefault : modelValues[0];
onInputChange(nextModel, currentModelField);
}
} else {
@ -401,8 +437,6 @@ const TextProvider = ({
</div>
{selectedProvider !== 'ollama' && selectedProvider !== 'codex' && (!modelsChecked || (modelsChecked && availableModels.length === 0)) && (
<button
@ -451,9 +485,15 @@ const TextProvider = ({
className="w-full h-12 px-4 py-4 outline-none border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-colors hover:border-gray-400 justify-between"
>
<span className="text-sm truncate font-medium text-gray-900">
{currentModel
? availableModels.find(model => model === currentModel) || currentModel
: "Select a model"}
{(() => {
if (!currentModel) return "Select a model";
const selectedModel = availableModels.find((model) => model.value === currentModel);
if (!selectedModel) return currentModel;
if (selectedProvider === 'ollama' && selectedModel.size) {
return `${selectedModel.label} (${selectedModel.size})`;
}
return selectedModel.label;
})()}
</span>
<ChevronUp className="w-4 h-4 text-gray-500" />
@ -469,13 +509,13 @@ const TextProvider = ({
<CommandList>
<CommandEmpty>No model found.</CommandEmpty>
<CommandGroup>
{availableModels.map((model, index) => (
{availableModels.map((model) => (
<CommandItem
key={index}
value={model}
onSelect={(value) => {
key={model.value}
value={model.value}
onSelect={() => {
if (currentModelField) {
onInputChange(value, currentModelField);
onInputChange(model.value, currentModelField);
}
setOpenModelSelect(false);
}}
@ -483,7 +523,7 @@ const TextProvider = ({
<Check
className={cn(
"mr-2 h-4 w-4",
currentModel === model
currentModel === model.value
? "opacity-100"
: "opacity-0"
)}
@ -492,8 +532,13 @@ const TextProvider = ({
<div className="flex flex-col space-y-1 flex-1">
<div className="flex items-center justify-between gap-2">
<span className="text-sm font-medium text-gray-900">
{model}
{model.label}
</span>
{selectedProvider === 'ollama' && model.size ? (
<span className="text-xs font-medium text-gray-500">
{model.size}
</span>
) : null}
</div>
</div>
</div>

View file

@ -22,15 +22,23 @@ export const PRISM_CODE_BLOCK_STYLES = `
white-space: inherit !important;
}
.prism-code-block {
--code-fg: var(--background-text, #dbe5ff);
--code-accent: var(--primary-color, #7aa2ff);
color: var(--code-fg);
}
.prism-code-block .token.comment,
.prism-code-block .token.prolog,
.prism-code-block .token.doctype,
.prism-code-block .token.cdata {
color: #7b8ebf;
color: var(--code-fg);
opacity: 0.62;
}
.prism-code-block .token.punctuation {
color: #a8b7e0;
color: var(--code-fg);
opacity: 0.82;
}
.prism-code-block .token.property,
@ -38,12 +46,14 @@ export const PRISM_CODE_BLOCK_STYLES = `
.prism-code-block .token.constant,
.prism-code-block .token.symbol,
.prism-code-block .token.deleted {
color: #7bc4ff;
color: var(--graph-0, #7bc4ff);
color: color-mix(in srgb, var(--graph-0, #7bc4ff) 72%, var(--code-fg) 28%);
}
.prism-code-block .token.boolean,
.prism-code-block .token.number {
color: #f5c97b;
color: var(--graph-1, #f5c97b);
color: color-mix(in srgb, var(--graph-1, #f5c97b) 68%, var(--code-fg) 32%);
}
.prism-code-block .token.selector,
@ -52,30 +62,36 @@ export const PRISM_CODE_BLOCK_STYLES = `
.prism-code-block .token.char,
.prism-code-block .token.builtin,
.prism-code-block .token.inserted {
color: #9fe6b8;
color: var(--graph-2, #9fe6b8);
color: color-mix(in srgb, var(--graph-2, #9fe6b8) 72%, var(--code-fg) 28%);
}
.prism-code-block .token.operator,
.prism-code-block .token.entity,
.prism-code-block .token.url,
.prism-code-block .token.variable {
color: #f5a97f;
color: var(--graph-3, #f5a97f);
color: color-mix(in srgb, var(--graph-3, #f5a97f) 70%, var(--code-fg) 30%);
}
.prism-code-block .token.atrule,
.prism-code-block .token.attr-value,
.prism-code-block .token.function,
.prism-code-block .token.class-name {
color: #b8a8ff;
color: var(--graph-4, #b8a8ff);
color: color-mix(in srgb, var(--graph-4, #b8a8ff) 74%, var(--code-fg) 26%);
}
.prism-code-block .token.keyword {
color: #7aa2ff;
color: var(--code-accent);
color: color-mix(in srgb, var(--code-accent, #7aa2ff) 78%, var(--code-fg) 22%);
font-weight: 600;
}
.prism-code-block .token.regex,
.prism-code-block .token.important {
color: #f9e2af;
color: var(--code-accent);
color: color-mix(in srgb, var(--code-accent, #7aa2ff) 64%, var(--graph-1, #f5c97b) 36%);
}
`;