Abigail/embedding OpenAI base url (#1068)
* fix(cli): write embedding base url in --setup * feat(cli): surface local stack on the welcome screen
This commit is contained in:
parent
9e60f73c7f
commit
cccfa988f8
|
|
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Fixed
|
||||
|
||||
- `--setup` for openai-compatible writes `EMBEDDING_MODEL_CONFIG__OVERRIDES__BASE_URL` into the profile `.env` alongside `LLM_OPENAI_BASE_URL`
|
||||
|
||||
## [0.1.3] - 2026-08-25
|
||||
|
||||
### Added
|
||||
|
|
|
|||
|
|
@ -59,16 +59,21 @@ def _welcome_panel(title: str, rows: list[tuple[str, str]]) -> Panel:
|
|||
|
||||
|
||||
def print_welcome(console: Console) -> None:
|
||||
"""Render the curated 3-panel welcome (banner + getting started / memory / commands)."""
|
||||
"""Render the curated welcome (banner + getting started / local stack / commands / memory)."""
|
||||
if use_json():
|
||||
return
|
||||
console.print(f"[bold {BRAND}]{BANNER}[/bold {BRAND}]")
|
||||
console.print(f" [dim]v{__version__}[/dim]\n", highlight=False)
|
||||
|
||||
start_rows = [
|
||||
("honcho init", "configure API key and server URL"),
|
||||
("honcho start", "run a local Honcho stack (Docker)"),
|
||||
("honcho doctor", "verify connection and workspace health"),
|
||||
("honcho init", "configure API key and server URL"),
|
||||
("honcho start [--setup basic]", "run a local Honcho stack (Docker)"),
|
||||
("honcho doctor", "verify connection and workspace health"),
|
||||
]
|
||||
stack_rows = [
|
||||
("honcho start / status / stop", "lifecycle for the local Docker stack"),
|
||||
("honcho start --setup basic", "interactive LLM + feature wizard"),
|
||||
("HONCHO_BASE_URL=http://127.0.0.1:8000", "prefix any command — CLI stays on api.honcho.dev until you set this"),
|
||||
]
|
||||
cmd_rows = [
|
||||
("[dim]pattern[/dim]", r"[dim]honcho <command> \[args] \[-w workspace] \[-p peer] \[-s session][/dim]"),
|
||||
|
|
@ -85,14 +90,15 @@ def print_welcome(console: Console) -> None:
|
|||
("config", "inspect current configuration"),
|
||||
]
|
||||
memory_rows = [
|
||||
("honcho peer chat \"...\" -p <peer> -w <workspace>","query the Dialectic about a peer"),
|
||||
("honcho peer inspect -p <peer> -w <workspace>","dashboard: peer card + recent conclusions + configuration"),
|
||||
("honcho peer chat \"...\" -p <peer> -w <workspace>", "query the Dialectic about a peer"),
|
||||
("honcho peer inspect -p <peer> -w <workspace>", "dashboard: peer card + recent conclusions + configuration"),
|
||||
("honcho peer representation -p <peer> -w <workspace>", "global peer representation"),
|
||||
("honcho peer representation -p <peer> -w <workspace> -s <session>", "session-scoped peer representation"),
|
||||
("honcho peer card -p <peer> -w <workspace>", "synthesized identity: traits, preferences, instructions"),
|
||||
("honcho conclusion list -p <peer> -w <workspace>", "browse peer conclusions"),
|
||||
("honcho conclusion list -p <peer> -w <workspace>", "browse peer conclusions"),
|
||||
("honcho session view / context -s <session>", "transcript, or what an agent would see"),
|
||||
("honcho workspace queue-status", "is the deriver processing?"),
|
||||
]
|
||||
|
||||
option_rows = [
|
||||
("-w / --workspace", "scope to a workspace"),
|
||||
("-p / --peer", "scope to a peer"),
|
||||
|
|
@ -102,6 +108,7 @@ def print_welcome(console: Console) -> None:
|
|||
]
|
||||
|
||||
console.print(_welcome_panel("getting started", start_rows))
|
||||
console.print(_welcome_panel("local stack", stack_rows))
|
||||
console.print(_welcome_panel("commands", cmd_rows))
|
||||
console.print(_welcome_panel("memory", memory_rows))
|
||||
console.print(_welcome_panel("options", option_rows))
|
||||
|
|
|
|||
|
|
@ -14,11 +14,7 @@ from pathlib import Path
|
|||
import typer
|
||||
from rich.console import Console
|
||||
|
||||
from honcho_cli.local.env import (
|
||||
is_placeholder_key,
|
||||
read_env_file,
|
||||
settings_from_environ,
|
||||
)
|
||||
from honcho_cli.local.env import is_placeholder_key, read_env_file, settings_from_environ
|
||||
from honcho_cli.output import print_error
|
||||
|
||||
SETUP_MODES = ("basic", "advanced")
|
||||
|
|
@ -145,6 +141,10 @@ def answers_to_env(answers: SetupAnswers) -> dict[str, str]:
|
|||
env[_PROVIDER_KEY_ENV[answers.provider]] = answers.api_key
|
||||
if answers.base_url:
|
||||
env["LLM_OPENAI_BASE_URL"] = answers.base_url
|
||||
# Embeddings do not inherit this URL; write it so OpenRouter/vLLM
|
||||
# keys are not sent to api.openai.com.
|
||||
if (answers.embedding_transport or "openai") == "openai":
|
||||
env["EMBEDDING_MODEL_CONFIG__OVERRIDES__BASE_URL"] = answers.base_url
|
||||
|
||||
if answers.embedding_api_key and answers.embedding_key_transport:
|
||||
embed_key = (
|
||||
|
|
@ -188,9 +188,13 @@ def answers_to_env(answers: SetupAnswers) -> dict[str, str]:
|
|||
|
||||
def answers_drop_keys(answers: SetupAnswers) -> tuple[str, ...]:
|
||||
"""Keys to remove so a previous wizard run cannot leak into this one."""
|
||||
if answers.provider == "openai-compatible":
|
||||
return ()
|
||||
return ("LLM_OPENAI_BASE_URL",)
|
||||
drop: list[str] = []
|
||||
if answers.provider != "openai-compatible":
|
||||
drop.append("LLM_OPENAI_BASE_URL")
|
||||
embed_openai = (answers.embedding_transport or "openai") == "openai"
|
||||
if answers.provider != "openai-compatible" or not embed_openai:
|
||||
drop.append("EMBEDDING_MODEL_CONFIG__OVERRIDES__BASE_URL")
|
||||
return tuple(drop)
|
||||
|
||||
|
||||
def run_setup(
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from __future__ import annotations
|
|||
from honcho_cli.local.setup import (
|
||||
DIALECTIC_LEVELS,
|
||||
SetupAnswers,
|
||||
answers_drop_keys,
|
||||
answers_to_env,
|
||||
chat_model_default,
|
||||
load_toml_setup_defaults,
|
||||
|
|
@ -46,6 +47,33 @@ def test_basic_anthropic_keeps_openai_embeddings_default():
|
|||
assert "EMBEDDING_MODEL_CONFIG__TRANSPORT" not in env
|
||||
|
||||
|
||||
def test_openai_compatible_copies_base_url_to_embeddings():
|
||||
env = answers_to_env(
|
||||
SetupAnswers(
|
||||
mode="basic",
|
||||
provider="openai-compatible",
|
||||
api_key="sk-or-test",
|
||||
chat_model="gpt-test",
|
||||
base_url="https://openrouter.ai/api/v1",
|
||||
)
|
||||
)
|
||||
assert env["LLM_OPENAI_BASE_URL"] == "https://openrouter.ai/api/v1"
|
||||
assert (
|
||||
env["EMBEDDING_MODEL_CONFIG__OVERRIDES__BASE_URL"]
|
||||
== "https://openrouter.ai/api/v1"
|
||||
)
|
||||
|
||||
|
||||
def test_leaving_openai_compatible_drops_proxy_urls():
|
||||
dropped = answers_drop_keys(
|
||||
SetupAnswers(
|
||||
mode="basic", provider="openai", api_key="sk", chat_model="gpt-test"
|
||||
)
|
||||
)
|
||||
assert "LLM_OPENAI_BASE_URL" in dropped
|
||||
assert "EMBEDDING_MODEL_CONFIG__OVERRIDES__BASE_URL" in dropped
|
||||
|
||||
|
||||
def test_chat_default_comes_from_image_toml(tmp_path):
|
||||
path = tmp_path / "config.toml"
|
||||
path.write_text(
|
||||
|
|
|
|||
Loading…
Reference in New Issue