fix(config): rename owlen cloud api key env
This commit is contained in:
@@ -169,7 +169,7 @@
|
||||
[providers.ollama_cloud]
|
||||
enabled = true
|
||||
base_url = "https://api.ollama.com" # [Inference] default
|
||||
api_key = "" # read from env OLLEN_OLLAMA_CLOUD_API_KEY if empty
|
||||
api_key = "" # read from env OWLEN_OLLAMA_CLOUD_API_KEY if empty
|
||||
hourly_quota_tokens = 50000 # configurable; visual only
|
||||
weekly_quota_tokens = 250000 # configurable; visual only
|
||||
list_ttl_secs = 60
|
||||
|
||||
90
agents-2025-10-23.md
Normal file
90
agents-2025-10-23.md
Normal file
@@ -0,0 +1,90 @@
|
||||
## fix(config): align ollama cloud defaults with api host
|
||||
- **Severity:** High – cloud calls 404 because defaults still point at `https://ollama.com` and require `OLLAMA_CLOUD_API_KEY` (`crates/owlen-core/src/config.rs:26`, `config.toml:16`, `README.md:6`).
|
||||
- **Issue:** Fresh installs silently fail against Ollama Cloud; env naming diverges from the spec (`OWLEN_OLLAMA_CLOUD_API_KEY` vs vendor-provided `OLLAMA_API_KEY`) so doctor tooling cannot guide users.
|
||||
- **Plan:** Switch canonical host to `https://api.ollama.com`, teach config loaders to honor the new env while warning on the legacy name, and update generated configs, doctor output, and docs.
|
||||
- **Acceptance Criteria:** New configs hit cloud without manual overrides; legacy env keeps working with a single warning; `owlen providers status` shows cloud reachable when the key is set.
|
||||
- **Test Notes:** Extend `Config` env resolution tests, add CLI smoke test for status under both env names, and run `cargo test -p owlen-core -p owlen-cli`.
|
||||
|
||||
## fix(provider/ollama): keep stream whitespace intact
|
||||
- **Severity:** High – `generate_stream` trims every line so assistants lose leading newlines and indentation (`crates/owlen-providers/src/ollama/shared.rs:135` and :161).
|
||||
- **Issue:** Markdown blocks and code fences arrive malformed, forcing the UI to patch formatting after the fact.
|
||||
- **Plan:** Replace the naive `trim()` with CR/LF stripping that preserves user-visible whitespace, keep incomplete line fragments buffered, and add defensive logging around JSON decode failures.
|
||||
- **Acceptance Criteria:** Streaming chunks can start with whitespace (code blocks render correctly); end-of-stream metadata still lands in the final message; no regressions for local or cloud daemons.
|
||||
- **Test Notes:** Add unit tests that feed `\r\n`-terminated chunks with leading spaces, plus an integration test using recorded `samples.json`; run `cargo test -p owlen-providers`.
|
||||
|
||||
## feat(provider/ollama): wire tool calling and response metadata
|
||||
- **Severity:** High – Ollama models never see tool descriptors because `prepare_chat_request` drops them and `supports_tools` is hard-coded false (`crates/owlen-core/src/providers/ollama.rs:825` and :1258).
|
||||
- **Issue:** The agent pipeline cannot hand off `web.search` or other tools; chat stalls when the model requests a function call.
|
||||
- **Plan:** Send tool schemas to Ollama, surface tool_call deltas back into `ChatResponse`, mark capable models as tool-ready, and ensure session handling replays tool results before resuming generation.
|
||||
- **Acceptance Criteria:** Models that emit tool calls loop through the MCP tool registry without manual intervention; disabling tools blanks them out; streaming transcripts keep tool boundaries.
|
||||
- **Test Notes:** Add provider tests covering `tool_calls` frames, extend session streaming tests with mock tool responses, and run `cargo test -p owlen-core`.
|
||||
|
||||
## feat(usage): track cloud token quotas and expose :limits
|
||||
- **Severity:** Medium – there is no hourly/weekly accounting or `:limits` command even though the UI promises it (`crates/owlen-core/src/session.rs`, `crates/owlen-tui/src/chat_app.rs:6880` area, `crates/owlen-tui/src/ui.rs:2280` area).
|
||||
- **Issue:** Users cannot see or cap consumption, and the header lacks the cloud usage line from the spec.
|
||||
- **Plan:** Introduce a persisted usage ledger (rolling hour/week windows) keyed by provider, surface quotas from config, add `:limits` to the palette, and render an extra header row with colored percentages plus 80%/95% toasts.
|
||||
- **Acceptance Criteria:** Usage survives restart, `:limits` prints hourly and weekly tallies, header updates after each completion, and quota breaches raise a toast once per band.
|
||||
- **Test Notes:** Write time-travel unit tests for the tracker, snapshot the new header rendering, add a TUI command test, and run `cargo test -p owlen-core -p owlen-tui`.
|
||||
|
||||
## feat(tool/web): route searches through provider and gate on cloud availability
|
||||
- **Severity:** High – `web_search` hits DuckDuckGo directly (`crates/owlen-core/src/tools/web_search.rs:14`) and the registry exposes it even when the cloud provider is disabled (`crates/owlen-core/src/session.rs:245` range).
|
||||
- **Issue:** In restricted environments the tool fails silently, and the model keeps saying it lacks internet access despite the stated goal.
|
||||
- **Plan:** Replace the DuckDuckGo client with a provider-aware adapter that calls the configured cloud search endpoint, hide the tool unless the active provider advertises web search support, and surface clean errors for 401/429 responses.
|
||||
- **Acceptance Criteria:** With a valid cloud key the assistant auto-invokes `web.search`; without cloud access the tool is absent and the model does not ask for it; detailed errors reach the toast system.
|
||||
- **Test Notes:** Add Wiremock-backed integration tests for happy path, 401, and 429; assert tool registration toggles via session tests; run `cargo test -p owlen-core --tests tools`.
|
||||
|
||||
## feat(ui): modernize chat chrome and usage surfacing
|
||||
- **Severity:** Medium – the current TUI still uses heavy bordered blocks and text badges (`crates/owlen-tui/src/ui.rs:200` onward) and lacks the cockpit-style progress bars requested for context and usage.
|
||||
- **Issue:** Visual hierarchy is dated, the context badge is text-only, and screenshots (`images/layout.png`) no longer match the roadmap.
|
||||
- **Plan:** Refresh the header with gradient bars for context and cloud usage, adopt lighter glassmorphism-inspired panels, tighten spacing, update themes, and regenerate screenshots for docs.
|
||||
- **Acceptance Criteria:** Header shows context and usage bars with color thresholds, panels use the new styling without breaking vim keybinds, and updated screenshots appear in docs.
|
||||
- **Test Notes:** Update golden snapshot tests for the layout, add UI smoke tests for narrow terminals, and capture new PNGs via the existing screenshot script.
|
||||
|
||||
## docs(release): prep v0.2 guidance and config samples
|
||||
- **Severity:** Medium – public docs still advertise v0.1.11 and outdated setup steps (`README.md:6`, `docs/troubleshooting.md`, `AGENTS.md` samples out of sync with actual config schema).
|
||||
- **Issue:** Users follow stale instructions, miss new keys (hourly/weekly quotas), and cannot reconcile the config example with generated files.
|
||||
- **Plan:** Bump version strings to v0.2, document the new config sections (quotas, list TTL), add troubleshooting for cloud auth and rate limits, and note the revised env naming.
|
||||
- **Acceptance Criteria:** README, docs, and sample configs match the implemented features; upgrade notes explain migration steps; release checklist reflects the new DoD.
|
||||
- **Test Notes:** Run link checker over `docs/`, lint Markdown with `cargo xtask lint-docs`, and have CI confirm the changelog entry.
|
||||
|
||||
## feat(commands): expose `:web on|off` toggle in both TUI and CLI
|
||||
- **Severity:** Medium – there is no runtime switch for the web-search tool (`crates/owlen-tui/src/commands/registry.rs`, `crates/owlen-tui/src/chat_app.rs`), so users must hand-edit config to disable remote lookups when on metered links.
|
||||
- **Issue:** Lack of a fast toggle contradicts the DoD requirement for obvious tooling controls and encourages unsafe defaults when privacy-sensitive users need a local-only session.
|
||||
- **Plan:** Add `:web on|off` and `owlen providers web --enable/--disable` commands that mutate `config.tools.web_search.enabled`, broadcast the change to active sessions, and synchronise the header indicator/toast copy.
|
||||
- **Acceptance Criteria:** Toggling via command takes effect immediately (tool descriptors disappear/appear for the next request), the setting persists to disk, and both CLI+TUI help list the new flags.
|
||||
- **Test Notes:** Extend command registry unit tests, add an integration test that toggles and asserts tool exposure, and validate persistence with a temporary config dir.
|
||||
|
||||
## feat(config): align generated config with provider sections & env fallbacks
|
||||
- **Severity:** Medium – the sample `config.toml` and `README` snippets still use flat `[providers.ollama_cloud]` keys with `api_key_env = "OLLAMA_CLOUD_API_KEY"` and base URL `https://ollama.com` (`config.toml:16`, `README.md:119`), diverging from `crates/owlen-core/src/config.rs`.
|
||||
- **Issue:** Onboarding breaks because the UI and doctor expect the `[providers.ollama_cloud]` schema with `OWLEN_OLLAMA_CLOUD_API_KEY` and `[providers.ollama]` defaults, so fresh installs require manual correction.
|
||||
- **Plan:** Regenerate the CLI templated config, update documentation snippets, implement migration warnings for the legacy env name, and ensure doctor explains both env vars with precedence.
|
||||
- **Acceptance Criteria:** `owlen config init` writes the new schema, doctor reports actionable guidance when the legacy env is present, and README/config docs match the generated file.
|
||||
- **Test Notes:** Snapshot regeneration output, add config migration tests covering legacy envs, and run `cargo test -p owlen-core config` suite.
|
||||
|
||||
## refactor(errors): typed provider failures mapped to structured toasts
|
||||
- **Severity:** High – the TUI currently inspects error strings for `"429"` / `"rate limit"` substrings (`crates/owlen-tui/src/chat_app.rs:10377`) and loses context when providers change wording.
|
||||
- **Issue:** String matching misses localized messages and risks leaking raw responses into the UI, preventing reliable recovery and localisation.
|
||||
- **Plan:** Introduce a typed error enum in `owlen-core` (`Error::Unauthorized`, `::RateLimited`, `::Unavailable`, etc.), propagate it through providers, and map the variants to toast/banners with deterministic copy.
|
||||
- **Acceptance Criteria:** Cloud 401/429 cases surface the new typed variants, the UI no longer string-parses errors, logs redact secrets, and analytics tests assert the mapping.
|
||||
- **Test Notes:** Extend provider unit tests for HTTP status translation, add UI tests that inject each error variant, and fuzz unknown error text to ensure graceful fallback.
|
||||
|
||||
## test(integration): cover local/cloud/search tool happy and unhappy paths
|
||||
- **Severity:** Medium – there are no Wiremock-backed integration cases validating multi-provider flows; regressions slip through (`crates/owlen-core/tests` lacks HTTP stubs).
|
||||
- **Issue:** Streaming/tool-call regressions and auth handling bugs reach users because only unit tests exist.
|
||||
- **Plan:** Create integration tests that spin up stub servers for `/api/tags`, `/api/chat`, and `/v1/web/search`, covering 200/401/429 responses, tool-call loops, and rate-limit recovery.
|
||||
- **Acceptance Criteria:** CI runs the new suite, failures are deterministic, and each scenario asserts provider status transitions plus persisted usage updates.
|
||||
- **Test Notes:** Use `wiremock` for HTTP stubbing, reuse sample transcripts from `samples.json`, and document the fixtures under `tests/fixtures/`.
|
||||
|
||||
## chore(deps/ui): upgrade to Ratatui 0.29+ and enable gradient widgets
|
||||
- **Severity:** Medium – we pin `ratatui = 0.28` and `crossterm = 0.28` (`Cargo.toml`), missing gradient fills, flexible layout APIs, and native mouse handling released in 2025.
|
||||
- **Issue:** Without the newer widgets we hand-roll gradients/badges and duplicate layout math, increasing maintenance debt.
|
||||
- **Plan:** Bump Ratatui/Crossterm, adopt the `Gauge` gradient support for context/usage bars, replace custom layout helpers with the new `Flex` API, and ensure theme palettes cover extended colour spaces.
|
||||
- **Acceptance Criteria:** Build succeeds with the upgraded stack, header widgets use the new gradient gauges, and CI snapshots reflect the refreshed rendering.
|
||||
- **Test Notes:** Run `cargo test -p owlen-tui`, update golden snapshots, and manually verify mouse/resize handling in the demo app.
|
||||
|
||||
## chore(release): bump workspace metadata to v0.2
|
||||
- **Severity:** Medium – the workspace version, crates, and README badges still say 0.1.11 (`Cargo.toml`, `README.md:8`), undermining the v0.2 delivery narrative.
|
||||
- **Issue:** Packaging scripts (AUR, PKGBUILD) and CLI `--version` output disagree with the roadmap, confusing users and automated installers.
|
||||
- **Plan:** Update `[workspace.package].version`, propagate the bump to crate manifests, adjust badges/screenshots, and refresh packaging metadata (PKGBUILD, docs/CHANGELOG).
|
||||
- **Acceptance Criteria:** `owlen --version` prints 0.2.0, README badges align, and release notes enumerate the v0.2 features.
|
||||
- **Test Notes:** Run `cargo xtask lint-release`, build the Arch package locally, and smoke-test binary version output.
|
||||
@@ -23,8 +23,14 @@ pub const OLLAMA_MODE_KEY: &str = "ollama_mode";
|
||||
/// Extra config key storing the preferred Ollama Cloud endpoint.
|
||||
pub const OLLAMA_CLOUD_ENDPOINT_KEY: &str = "cloud_endpoint";
|
||||
/// Canonical Ollama Cloud base URL.
|
||||
pub const OLLAMA_CLOUD_BASE_URL: &str = "https://ollama.com";
|
||||
/// Environment variable used for Ollama Cloud authentication.
|
||||
pub const OLLAMA_CLOUD_BASE_URL: &str = "https://api.ollama.com";
|
||||
/// Legacy Ollama Cloud base URL (accepted for backward compatibility).
|
||||
pub const LEGACY_OLLAMA_CLOUD_BASE_URL: &str = "https://ollama.com";
|
||||
/// Preferred environment variable used for Ollama Cloud authentication.
|
||||
pub const OWLEN_OLLAMA_CLOUD_API_KEY_ENV: &str = "OWLEN_OLLAMA_CLOUD_API_KEY";
|
||||
/// Legacy environment variable accepted for backward compatibility.
|
||||
pub const LEGACY_OLLEN_OLLAMA_CLOUD_API_KEY_ENV: &str = "OLLEN_OLLAMA_CLOUD_API_KEY";
|
||||
/// Legacy environment variable still accepted for Ollama Cloud authentication.
|
||||
pub const OLLAMA_CLOUD_API_KEY_ENV: &str = "OLLAMA_CLOUD_API_KEY";
|
||||
/// Default base URL for local Ollama daemons.
|
||||
pub const OLLAMA_LOCAL_BASE_URL: &str = "http://localhost:11434";
|
||||
@@ -681,8 +687,13 @@ impl Config {
|
||||
if cloud.base_url.is_none() {
|
||||
cloud.base_url = Some(OLLAMA_CLOUD_BASE_URL.to_string());
|
||||
}
|
||||
if cloud.api_key_env.is_none() {
|
||||
cloud.api_key_env = Some(OLLAMA_CLOUD_API_KEY_ENV.to_string());
|
||||
if cloud.api_key_env.is_none()
|
||||
|| cloud
|
||||
.api_key_env
|
||||
.as_deref()
|
||||
.is_some_and(|value| value == LEGACY_OLLEN_OLLAMA_CLOUD_API_KEY_ENV)
|
||||
{
|
||||
cloud.api_key_env = Some(OWLEN_OLLAMA_CLOUD_API_KEY_ENV.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -830,7 +841,7 @@ fn default_ollama_cloud_config() -> ProviderConfig {
|
||||
provider_type: canonical_provider_type("ollama_cloud"),
|
||||
base_url: Some(OLLAMA_CLOUD_BASE_URL.to_string()),
|
||||
api_key: None,
|
||||
api_key_env: Some(OLLAMA_CLOUD_API_KEY_ENV.to_string()),
|
||||
api_key_env: Some(OWLEN_OLLAMA_CLOUD_API_KEY_ENV.to_string()),
|
||||
extra,
|
||||
}
|
||||
}
|
||||
@@ -918,7 +929,10 @@ fn is_cloud_base_url(base_url: Option<&String>) -> bool {
|
||||
base_url
|
||||
.map(|url| {
|
||||
let trimmed = url.trim_end_matches('/');
|
||||
trimmed == OLLAMA_CLOUD_BASE_URL || trimmed.starts_with("https://ollama.com/")
|
||||
trimmed == OLLAMA_CLOUD_BASE_URL
|
||||
|| trimmed == LEGACY_OLLAMA_CLOUD_BASE_URL
|
||||
|| trimmed.starts_with("https://ollama.com/")
|
||||
|| trimmed.starts_with("https://api.ollama.com/")
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
@@ -36,7 +36,10 @@ use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
Error, Result,
|
||||
config::{GeneralSettings, OLLAMA_CLOUD_BASE_URL, OLLAMA_CLOUD_ENDPOINT_KEY, OLLAMA_MODE_KEY},
|
||||
config::{
|
||||
GeneralSettings, LEGACY_OLLEN_OLLAMA_CLOUD_API_KEY_ENV, OLLAMA_CLOUD_BASE_URL,
|
||||
OLLAMA_CLOUD_ENDPOINT_KEY, OLLAMA_MODE_KEY, OWLEN_OLLAMA_CLOUD_API_KEY_ENV,
|
||||
},
|
||||
llm::{LlmProvider, ProviderConfig},
|
||||
mcp::McpToolDescriptor,
|
||||
model::{DetailedModelInfo, ModelDetailsCache, ModelManager},
|
||||
@@ -387,6 +390,8 @@ impl OllamaProvider {
|
||||
|
||||
let mut api_key = resolve_api_key(config.api_key.clone())
|
||||
.or_else(|| resolve_api_key_env_hint(config.api_key_env.as_deref()))
|
||||
.or_else(|| env_var_non_empty(OWLEN_OLLAMA_CLOUD_API_KEY_ENV))
|
||||
.or_else(|| env_var_non_empty(LEGACY_OLLEN_OLLAMA_CLOUD_API_KEY_ENV))
|
||||
.or_else(|| env_var_non_empty("OLLAMA_API_KEY"))
|
||||
.or_else(|| env_var_non_empty("OLLAMA_CLOUD_API_KEY"));
|
||||
let api_key_present = api_key.is_some();
|
||||
|
||||
Reference in New Issue
Block a user