feat(connectors): add Ollama and LM Studio as a local auth kind

Both servers expose OpenAI-compatible /v1/chat/completions and /v1/models,
so we route them through pi-ai's `openai-completions` API the same way
Fireworks does — but with a per-installation base URL the user enters
during onboarding instead of a hardcoded one. The shared schemas grow a
`local` credential payload carrying just the baseUrl; the credential
resolver surfaces it on `ResolvedCredential.baseUrl`, the runtime bridge
forwards it through `prepareRun`, and the worker plumbs it into
`resolveModel` so the streamed Model<openai-completions> targets the
user's server. The local-cost path short-circuits to zero in cost-writer
since users bill their own hardware, and the live model list is fetched
from the saved baseUrl by `fetchLocalConnectorModels` (Ollama and LM
Studio both speak the standard OpenAI catalog shape). Onboarding ships
a new LocalProviderCard and the Settings panel a LocalForm; both default
to the catalog's per-connector localhost URL and accept any custom URL.
This commit is contained in:
ZacharyZhang-NY committed 2026-05-14 14:55:38 -04:00
1 parent 07d9c00fab
commit a532120649
26 files changed
+504 -18

No files matched your search

+5 -1
View File
@@ -19,6 +19,8 @@ interface PrepareRunResult {
provider: string;
apiKey: string;
extraEnv: Record<string, string>;
/** OpenAI-compatible server base URL for local connectors (Ollama, LM Studio). */
baseUrl: string | null;
priorMessages: AgentMessage[];
}
@@ -133,7 +135,9 @@ export class WorkerRunner {
const runEnv = mergeRunEnvs(job.env, prepared.extraEnv);
redact = buildRedactor(runEnv);
const model = resolveModel(prepared.provider, job.model);
const model = resolveModel(prepared.provider, job.model, {
baseUrl: prepared.baseUrl ?? undefined,
});
if (!model) {
throw new Error(`Unknown model ${job.model} for provider ${prepared.provider}.`);
}