diff --git a/build.zig.zon b/build.zig.zon index 9b9ec5429..7a0eae81c 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -35,8 +35,8 @@ .hash = "sqlite3-3.51.0-DMxLWssOAABZ8cAvU_LfBIbp0kZjm824PU8sSLXpEDdr", }, .zenai = .{ - .url = "git+https://github.com/lightpanda-io/zenai.git#3f9315fdf390b37ee8bda55f7e454327b0c1d931", - .hash = "zenai-0.0.0-iOY_VJSBBADUifICag2s31rv-XZZ924Be_MVXXxFx22S", + .url = "git+https://github.com/lightpanda-io/zenai.git#d62ee4bb8afdc675256c753cb9d86f4c85c37c92", + .hash = "zenai-0.0.0-iOY_VM-CBABTsCxvb0ZqiWQkhu7Z9kWNBupPDCtEy-XJ", }, .isocline = .{ .url = "git+https://github.com/arrufat/isocline?ref=lightpanda#832a9fe25f5f4458fcc47b5acc7c21db669c2f47", diff --git a/src/agent/Agent.zig b/src/agent/Agent.zig index b36073bc6..0068fb552 100644 --- a/src/agent/Agent.zig +++ b/src/agent/Agent.zig @@ -291,14 +291,15 @@ pub fn init(allocator: std.mem.Allocator, app: *App, opts: Config.Agent) !*Agent // "No API key detected" for a run that does not need one. const resolve = !opts.no_llm and requires_llm; - // Print the banner before provider resolution so it precedes any - // interactive "Select a provider" prompt. On error paths (missing key / no - // key detected) resolveCredentials prints its own message; banner skipped. - if (will_repl and (!resolve or settings.wouldResolve(allocator, opts, remembered))) { - welcome.print(resolve); - } + // Print the banner before resolution so it precedes the interactive picker. + // The Ollama-only path never prompts, so its banner is deferred (below) to + // avoid probing the local server a second time just to decide ordering. + const banner_before = will_repl and (!resolve or settings.hasDetectableKey(opts, remembered)); + if (banner_before) welcome.print(resolve); const resolved: ?settings.ResolvedProvider = if (resolve) try settings.resolveCredentials(allocator, opts, remembered, will_repl) else null; + + if (will_repl and !banner_before and resolved != null) welcome.print(resolve); const llm: ?Credentials = if (resolved) |r| r.credentials else null; if (llm == null and requires_llm) { diff --git a/src/agent/settings.zig b/src/agent/settings.zig index e75bc42ba..1d70e499a 100644 --- a/src/agent/settings.zig +++ b/src/agent/settings.zig @@ -51,14 +51,14 @@ fn detectOllama(allocator: std.mem.Allocator, base_url: ?[:0]const u8) ?Credenti return .{ .provider = .ollama, .key = key }; } -/// Returns true when resolveCredentials would succeed (no error, non-null). -/// Used by callers that need to print a banner before calling resolveCredentials. -pub fn wouldResolve(allocator: std.mem.Allocator, opts: Config.Agent, remembered: ?Remembered) bool { +/// True when a non-Ollama provider key is available (flag, remembered, or +/// env-detected). Skips the Ollama probe so it isn't run twice at startup; the +/// interactive picker only fires on detected keys, which this still catches. +pub fn hasDetectableKey(opts: Config.Agent, remembered: ?Remembered) bool { if (opts.provider) |p| return zenai.provider.envApiKey(p) != null; if (remembered) |r| if (r.provider) |p| if (zenai.provider.envApiKey(p)) |_| return true; var buf: [zenai.provider.default_candidates.len]Credentials = undefined; - if (zenai.provider.detectKeys(&buf, zenai.provider.default_candidates).len > 0) return true; - return detectOllama(allocator, opts.base_url) != null; + return zenai.provider.detectKeys(&buf, zenai.provider.default_candidates).len > 0; } /// Precedence: `--provider` > remembered (if its key is still set) > first