LLeMbas CLI 1.0.0
ci / check (push) Waiting to run

The first public release of LLeMbas CLI: a terminal coding agent and project manager for any LLM
API, with permission modes, git snapshots, memory and skills, knowledge bases, MCP, voice, and a
link to a LLeMbas instance whose web UI can work its sessions too. Signed Linux binaries for x64
and arm64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
HomerandClaude Opus 5.5 committed 2026-10-09 21:59:03 +00:00
commit f9bad01ed7
355 files changed
+47028

No files matched your search

+70
View File
@@ -0,0 +1,70 @@
import { findRef, modelRefs } from "./refs.ts"
import type { Loaded } from "../config/load.ts"
import { AnthropicClient } from "./anthropic.ts"
import { OpenAIChatClient } from "./openai-chat.ts"
import { ResponsesClient } from "./responses.ts"
import { GeminiClient } from "./gemini.ts"
import { OllamaClient } from "./ollama.ts"
import { ProviderError, type Client, type ResolvedModel } from "./types.ts"
export class ModelError extends Error {}
/** `connection/model`. The model part may itself contain slashes (`openrouter/qwen/qwen3-coder`). */
export function resolveModel(loaded: Loaded, ref: string | undefined): ResolvedModel {
const refs = loaded.refs ?? modelRefs(loaded.connections)
if (!ref) {
// A LLeMbas instance says which model its account starts on; that, before anything else.
const instance = Object.entries(loaded.connections).find(([, c]) => c.webui?.default && c.models[c.webui.default])
if (instance) ref = refs.find((r) => r.connection === instance[0] && r.id === instance[1].webui!.default)?.ref ?? `${instance[0]}/${instance[1].webui!.default}`
}
if (!ref) {
const first = refs[0]
if (!first) throw new ModelError("No model configured. Add a connection to ~/.config/lembas/connections.yaml and set `model:` in config.yaml.")
ref = first.ref
}
// Any form of the name (`deepseek/x`, or the old `example/x`): the model it names, under
// the ref it has now.
const known = findRef(loaded.connections, refs, ref)
if (known) {
const connection = loaded.connections[known.connection]!
if (loaded.broken?.[known.connection]) throw new ModelError(`Connection "${known.connection}" is unusable: ${loaded.broken?.[known.connection]}`)
return { ref: known.ref, connectionName: known.connection, connection, id: known.id, spec: connection.models[known.id] ?? {} }
}
const slash = ref.indexOf("/")
if (slash <= 0) throw new ModelError(`Model "${ref}" must be written connection/model`)
const connectionName = ref.slice(0, slash)
const id = ref.slice(slash + 1)
if (loaded.broken?.[connectionName]) throw new ModelError(`Connection "${connectionName}" is unusable: ${loaded.broken[connectionName]}`)
const connection = loaded.connections[connectionName]
if (!connection) throw new ModelError(`No connection named "${connectionName}" (have: ${Object.keys(loaded.connections).join(", ") || "none"})`)
const spec = connection.models[id]
if (!spec && !connection.discover)
throw new ModelError(`Connection "${connectionName}" has no model "${id}" (have: ${Object.keys(connection.models).join(", ") || "none"}). Add it, or set discover: true.`)
return { ref, connectionName, connection, id, spec: spec ?? {} }
}
export function clientFor(m: ResolvedModel): Client {
switch (m.connection.dialect) {
case "openai-chat":
return new OpenAIChatClient(m)
case "anthropic":
return new AnthropicClient(m)
case "responses":
return new ResponsesClient(m)
case "gemini":
return new GeminiClient(m)
case "ollama":
return new OllamaClient(m)
}
}
/** Which prompt family a model gets when the config does not say: anthropic, gpt, gemini, or
* local — every open-weight or unknown model, which gets Hermes' act-don't-describe guidance. */
export function familyOf(m: ResolvedModel): string {
if (m.spec.family) return m.spec.family
const id = m.id.toLowerCase()
if (id.includes("claude")) return "anthropic"
if (id.includes("gemini")) return "gemini"
if (/\bgpt|^o[134]\b|^o[134]-|codex/.test(id)) return "gpt"
return "local"
}