Repository navigation
Conversation
Select a local Ollama model with MODEL_PROVIDER=ollama and OLLAMA_MODEL. OLLAMA_BASE_URL defaults to http://localhost:11434/v1 and no API key is required; OpenAI-compatible clients receive a placeholder bearer token and the OpenAI key is never forwarded. OpenAI remains the default and its settings resolve exactly as before. The setup card and Settings show the selected provider and offer a server-side check that lists the endpoint's models and explains when Ollama is not running or the configured model has not been pulled. Closes CopilotKit#100
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
OpenDots can use a local Ollama model without an API key. Set
MODEL_PROVIDER=ollamaandOLLAMA_MODELin.env;OLLAMA_BASE_URLdefaults tohttp://localhost:11434/v1. Ollama serves an OpenAI-compatible Chat Completions API, so Dot turns and research briefs use the existing TanStack AIopenaiCompatibleTextadapter and research request unchanged. OpenAI stays the default, and its settings resolve exactly as before.The first-run setup card and Settings & setup now show the selected model provider. On a fresh install they list both options: OpenAI with
OPENAI_API_KEYandOPENAI_MODEL, or Ollama withMODEL_PROVIDER=ollamaandOLLAMA_MODEL. With Ollama selected, Check Ollama asks the server to list the endpoint's models. The result appears as one status block under the button: an icon and a one-line headline, then at most one short next step. For example, "Ollama isn't running at http://localhost:11434/v1." followed by "Start it (open the Ollama app or runollama serve), then check again."Closes #100. Related to #118 and #87: this adds a local model option. Conversations still require CopilotKit Intelligence.
Changes
modelConfigFromEnvinsrc/server/platform-config.tsresolves the provider, key, model and base URL. Startup fails with a clear message for an unknownMODEL_PROVIDERor anOLLAMA_BASE_URLthat is not http(s) or contains credentials, query or fragment. A base URL without a path, such as Ollama'sOLLAMA_HOSTformhttp://localhost:11434, uses/v1.ollama, andOPENAI_API_KEYis never forwarded to the Ollama endpoint.setupStatusreportsOLLAMA_MODELas the only model setting Ollama needs, and stops asking forOPENAI_API_KEYwhen Ollama is selected. It addsmodelProvider, plusmodelBaseUrlfor Ollama only.OPENAI_BASE_URLmay point to a private proxy, so it stays server-side.GET /api/setup/model(src/server/model-check.ts): it callsGET {baseUrl}/modelsfrom the server with a 5-second timeout. It returns a one-sentencemessage, an optional one-linehint(backticks mark code), and the models worth offering: every model when the configured one is missing, otherwise the others (at most 50). None of these contain credentials or the provider's response body. Ollama'snameandname:latestmatch each other. The UI only shows the button for OpenAI once a key and model are configured.ModelSetupcomponent rendered in the setup card and the Settings service-setup note. It follows the existing design system:.connection-connectstyle. Its label reads "Check Ollama", then "Checking…" with theLoaderCircle/spinspinner, then "Check again".#438c81teal for success and the editor's save-error#9b4a32. Because they're hex values, the build step derives the dark theme.CircleCheckandCircleAlert), so status isn't conveyed by colour alone.type="button", so it doesn't submit the Settings form. While checking it setsaria-busyandaria-disabledrather thandisabled, so keyboard focus stays on it, and repeat presses are ignored.role="status"/aria-live="polite"region that the button references witharia-describedby. The region is cleared before each check so a repeated result is announced again.MODEL_PROVIDER,OLLAMA_BASE_URLandOLLAMA_MODEL..env.example,docs/SETUP.md(new Model provider section and connection-settings rows) and the README get-started and data-and-privacy text describe the option.Configuration lives in
.env, like the other providers. I didn't add a script or UI control that writes.env: the server reads it at startup, and the existing setup flow already tells the owner to edit it and restart.How to try it with Ollama
ollama pull llama3.2 # any model with tool-calling supportThen run
npm run dev, open http://127.0.0.1:5173, and select Check Ollama on the setup card or in Settings & setup. To see the error states, stop Ollama, or setOLLAMA_MODELto a model you haven't pulled. To chat, add an Intelligence key as before (hosted or local evaluation).Validation
tests/model-provider.test.ts:OPENAI_BASE_URLpassthrough.:latestmatch, not pulled, no models, server stopped, 404, and a non-JSON body./api/workspaceexposes the provider.DotAgentposts tohttp://localhost:11434/v1/chat/completionswithBearer ollamaand the Ollama model.tests/model-setup.test.tsx:aria-describedbywiring.aria-busy) to "Check again", with focus kept and repeat presses ignored. This test caught a double-request bug, now fixed.npm run check-format,npm run lint,npm run typecheck,npm test(56 files, 363 tests) andnpm run buildpass on Node 24.18.0.tests/telemetry.test.ts. That file passes on its own, and a rerun of the full suite passed.With real Ollama (0.40.5 on macOS, model
llama3.2:1b)npm run devwith onlyMODEL_PROVIDER=ollamaandOLLAMA_MODEL=llama3.2:1b, using the defaulthttp://localhost:11434/v1:/api/workspacereported the Ollama provider with no missing model setting. Only the Intelligence key was missing.With
OLLAMA_MODEL=llama3.2, a tag that isn't pulled locally, the check showed "Ollama doesn't have llama3.2 yet." and "Runollama pull llama3.2, then check again.", followed by the available models.With
OLLAMA_BASE_URLpointing to a port where nothing listens, the check showed "Ollama isn't running at …" and the one-line start instruction. I didn't stop the running Ollama to test this.Each state was checked in light and dark themes at 1280 px and 375 px, with no horizontal overflow. Measured WCAG contrast (light / dark):
The button border matches the existing outlined button (1.18:1 against the card); its text label identifies the control.
A Dot turn run directly through
DotAgent(the same TanStack adapter and tools the runtime uses) against real Ollama streamed a reply. It also completed a full tool round trip: the model calledcreate_space_page, the app executed it and returned the result, and the model continued.llama3.2:1bpassed malformed tool arguments, so no page was created, and it sometimes wrote tool-call JSON as plain text. These are model-quality limits; the docs recommend a model with tool support.A direct
max_completion_tokensrequest to this Ollama version returned normally.With a mock endpoint
Authorization: Bearer ollama, against a local mock of/v1/modelsand/v1/chat/completions.Not verified
DotAgentpath tested above, and conversation persistence isn't changed.llama3.2:1b. Larger tool-capable models (for examplellama3.23B orqwen3) weren't tested.host.docker.internalguidance in the docs comes from Docker Desktop's documented behavior, not from a test.I made this change with help from Claude Code: it drafted the code and tests and ran the checks above, and the diff was reviewed before this PR was opened.