Repository navigation
feat: add Ollama as a first-run model provider - #88
KayzenRoot wants to merge 1 commit into
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 #100
ECC Tools / Security EvidenceCommit: Security evidence gate passed (success) No security-sensitive scanner-evidence gap detected. Mode: enforce Scanned 17 changed file(s). No missing scanner-evidence signal was detected. Check publication was denied or unavailable. An app owner must enable Checks: read and write, and the installation owner must approve the updated permission. |
ECC Tools / PR Risk TaxonomyCommit: PR taxonomy review recommended (neutral) Detected 2 PR taxonomy bucket(s): CI/CD Recommendation, Cost/Token Risk. Scanned 17 changed file(s). Roadmap taxonomy buckets: CI/CD RecommendationCI, dependency, coverage, and contract signals should be routed into follow-up checks or verification work. Signals:
Paths:
Cost/Token RiskAI routing, usage, and token-budget changes should include budget or usage-limit evidence. Signals:
Paths:
Check publication was denied or unavailable. An app owner must enable Checks: read and write, and the installation owner must approve the updated permission. |
ECC Tools / Reference Set ReadinessCommit: Reference set readiness gaps detected (neutral) Reference evidence present for 0/7 areas (0%) across 17 changed file(s). This check is based on files changed in this PR. Repository-level readiness is still reported by
Check publication was denied or unavailable. An app owner must enable Checks: read and write, and the installation owner must approve the updated permission. |
ECC Tools / Hosted Promotion ReadinessCommit: Hosted promotion readiness passed (success) No hosted promotion evidence gaps detected across 17 changed file(s); 0 corpus scenarios had matching evidence. This check compares PR file changes against the evaluator/RAG promotion corpus in No evaluator corpus scenarios matched this PR. Check publication was denied or unavailable. An app owner must enable Checks: read and write, and the installation owner must approve the updated permission. |
|
Closing as part of the backlog triage. This fork replaced the hosted CopilotKit runtime with a self-hosted PostgreSQL-backed AG-UI runtime, so this patch was written against code that no longer exists in that form. The idea is preserved in the PR history and is worth reopening against the current runtime if it is still wanted — the branch and the diff stay available here. See docs/fork/EXECUTION-ORDER.md for how the remaining work is ordered. |
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 CopilotKit#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.