feat: add OllamaLocalExecutor and update provider handling

- Introduced OllamaLocalExecutor to handle requests for the "ollama-local" provider.
- Removed the direct URL construction for "ollama-local" from BaseExecutor.
- Updated index.js to include the new OllamaLocalExecutor in the executors mapping.
- Enhanced the ProvidersPage component to support dynamic addition of OpenAI/Anthropic compatible providers.
This commit is contained in:
decolua
2026-05-07 16:42:36 +07:00
parent 050e56f20b
commit 0d61a1d546
8 changed files with 127 additions and 94 deletions
@@ -6,6 +6,7 @@ import {
ReactFlow,
Handle,
Position,
Controls,
} from "@xyflow/react";
import "@xyflow/react/dist/style.css";
import { AI_PROVIDERS } from "@/shared/constants/providers";
@@ -250,13 +251,34 @@ export default function ProviderTopology({ providers = [], activeRequests = [],
);
const rfInstance = useRef(null);
const containerRef = useRef(null);
const fitOpts = { padding: 0.2, duration: 200 };
const onInit = useCallback((instance) => {
rfInstance.current = instance;
setTimeout(() => instance.fitView({ padding: 0.3 }), 50);
setTimeout(() => instance.fitView(fitOpts), 50);
}, []);
// Re-fit on container resize
useEffect(() => {
const el = containerRef.current;
if (!el) return;
const ro = new ResizeObserver(() => {
if (rfInstance.current) rfInstance.current.fitView(fitOpts);
});
ro.observe(el);
return () => ro.disconnect();
}, []);
// Re-fit when node count/layout changes
useEffect(() => {
if (rfInstance.current) {
const id = setTimeout(() => rfInstance.current.fitView(fitOpts), 50);
return () => clearTimeout(id);
}
}, [nodes.length]);
return (
<div className="h-[320px] w-full min-w-0 rounded-lg border border-border bg-bg-subtle/30 sm:h-[480px]">
<div ref={containerRef} className="h-[320px] w-full min-w-0 rounded-lg border border-border bg-bg-subtle/30 sm:h-[480px]">
{providers.length === 0 ? (
<div className="h-full flex items-center justify-center text-text-muted text-sm">
No providers connected
@@ -268,18 +290,22 @@ export default function ProviderTopology({ providers = [], activeRequests = [],
edges={edges}
nodeTypes={nodeTypes}
fitView
fitViewOptions={{ padding: 0.3 }}
fitViewOptions={fitOpts}
minZoom={0.1}
maxZoom={2}
onInit={onInit}
proOptions={{ hideAttribution: true }}
panOnDrag={false}
zoomOnScroll={false}
zoomOnPinch={false}
zoomOnDoubleClick={false}
panOnDrag
zoomOnScroll
zoomOnPinch
zoomOnDoubleClick
preventScrolling={false}
nodesDraggable={false}
nodesConnectable={false}
elementsSelectable={false}
/>
>
<Controls showInteractive={false} />
</ReactFlow>
)}
</div>
);