spacr.qt.ai.providers
Provider abstraction — one class per AI vendor. Each shells out to the vendor’s own coding-agent CLI so authentication piggy-backs on the user’s chat subscription (Claude.ai Pro, ChatGPT Plus/Pro/Team, Google account) — no separate API billing.
Anthropic Claude → the claude CLI (“Claude Code”)
OpenAI ChatGPT → the codex CLI
Google Gemini → the gemini CLI
- Each provider:
is_installed() — is the CLI on PATH? is_logged_in() — best-effort check; falls back to “assume yes if
installed” (the actual auth error surfaces on the first stream chunk).
stream_chat() — spawn the CLI subprocess, yield stdout chunks.
Conversation context is carried by concatenating the full message history into each prompt (simplest approach that works uniformly across all three CLIs). For subscription users token count is not a concern.
Module Contents
- class spacr.qt.ai.providers.ChatProvider[source]
Bases:
abc.ABCAbstract base for AI chat providers that shell out to a vendor CLI.
Subclasses set the
name/label/cli_name/install_hint/login_commandclass attributes and implementstream_chat().- Variables:
name – short id (“claude” / “codex” / “gemini”).
label – human-readable label shown in the UI.
cli_name – executable expected on
PATH.install_hint – shell one-liner suggested for installation.
login_command – shell one-liner the user runs to authenticate.
- is_logged_in() bool[source]
Best-effort — override per provider if a cheap check exists.
Default: assume yes when installed. The real auth error will surface as a normal subprocess failure on the first send.
- source_of_key() str[source]
Compat string for the old KeysDialog — now describes the CLI’s install/login state.
- class spacr.qt.ai.providers.ClaudeCliProvider[source]
Bases:
ChatProviderAnthropic Claude via the
claude(Claude Code) CLI.- install_hint = 'curl -fsSL https://claude.ai/install.sh | bash # or npm install -g @anthropic-ai/claude-code'[source]
- stream_chat(messages: List[Dict], system: str = '', model: str | None = None) Iterator[str][source]
Stream a chat completion from the
claudeCLI.- Parameters:
messages – conversation history as
{role, content}dicts.system – optional system prompt appended via
--append-system-prompt.model – optional model override passed via
--model.
- Returns:
iterator yielding stdout text chunks.
- class spacr.qt.ai.providers.CodexCliProvider[source]
Bases:
ChatProviderOpenAI ChatGPT via the
codexCLI.- stream_chat(messages: List[Dict], system: str = '', model: str | None = None) Iterator[str][source]
Stream a chat completion from the
codexCLI.- Parameters:
messages – conversation history as
{role, content}dicts.system – optional system prompt folded into the prompt body.
model – optional model override passed via
--model.
- Returns:
iterator yielding stdout text chunks.
- class spacr.qt.ai.providers.GeminiCliProvider[source]
Bases:
ChatProviderGoogle Gemini via the
geminiCLI.- stream_chat(messages: List[Dict], system: str = '', model: str | None = None) Iterator[str][source]
Stream a chat completion from the
geminiCLI.- Parameters:
messages – conversation history as
{role, content}dicts.system – optional system prompt folded into the prompt body.
model – optional model override passed via
-m.
- Returns:
iterator yielding stdout text chunks.
- spacr.qt.ai.providers.list_providers() List[ChatProvider][source]
Return every registered provider, regardless of install state.
- spacr.qt.ai.providers.configured_providers() List[ChatProvider][source]
Return only providers whose CLI is installed and logged in.
- spacr.qt.ai.providers.get_provider(name: str) ChatProvider | None[source]
Look up a registered provider by its short id.
- Parameters:
name – provider id (
"claude","codex","gemini").- Returns:
the matching provider, or
Noneif no such id.