mirror of
https://github.com/Twigpine/zero.git
synced 2026-11-08 09:49:34 -10:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca748c2b77 | ||
|
|
ef1a95a6ad |
No files matched your search
@@ -0,0 +1,49 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// SetActiveProviderEnv must export the provider name so a child process (whose
|
||||
// resolution reads the inherited environment via the nil-map -> os.Getenv path in
|
||||
// applyEnv) resolves the SAME active provider. A blank name CLEARS it.
|
||||
func TestSetActiveProviderEnvRoundTrips(t *testing.T) {
|
||||
t.Setenv(ActiveProviderEnv, "") // register cleanup; restores the original after
|
||||
|
||||
if err := os.Unsetenv(ActiveProviderEnv); err != nil {
|
||||
t.Fatalf("unset: %v", err)
|
||||
}
|
||||
SetActiveProviderEnv("") // blank with nothing set stays unset
|
||||
if got := os.Getenv(ActiveProviderEnv); got != "" {
|
||||
t.Fatalf("empty name set the env to %q, want unset", got)
|
||||
}
|
||||
|
||||
// Regression: switching from a named provider back to an unnamed/default profile
|
||||
// must CLEAR a previously exported value, not leave it stale for children.
|
||||
if err := os.Setenv(ActiveProviderEnv, "stale-provider"); err != nil {
|
||||
t.Fatalf("seed stale: %v", err)
|
||||
}
|
||||
SetActiveProviderEnv("") // blank must unset the stale value
|
||||
if got := os.Getenv(ActiveProviderEnv); got != "" {
|
||||
t.Fatalf("blank name left stale env %q, want cleared", got)
|
||||
}
|
||||
cfgStale := &FileConfig{}
|
||||
applyEnv(cfgStale, nil)
|
||||
if cfgStale.ActiveProvider != "" {
|
||||
t.Fatalf("applyEnv still resolved stale provider %q after clear", cfgStale.ActiveProvider)
|
||||
}
|
||||
|
||||
SetActiveProviderEnv("ollama-cloud")
|
||||
if got := os.Getenv(ActiveProviderEnv); got != "ollama-cloud" {
|
||||
t.Fatalf("env = %q, want ollama-cloud", got)
|
||||
}
|
||||
|
||||
// applyEnv with a nil map is the exact path a child uses: it falls back to
|
||||
// os.Getenv, so the inherited value selects the active provider.
|
||||
cfg := &FileConfig{}
|
||||
applyEnv(cfg, nil)
|
||||
if cfg.ActiveProvider != "ollama-cloud" {
|
||||
t.Fatalf("applyEnv ActiveProvider = %q, want ollama-cloud (inherited env not read)", cfg.ActiveProvider)
|
||||
}
|
||||
}
|
||||
@@ -431,8 +431,28 @@ func mergeProfile(base ProviderProfile, next ProviderProfile) ProviderProfile {
|
||||
return base
|
||||
}
|
||||
|
||||
// ActiveProviderEnv selects the active provider profile by name (read in applyEnv).
|
||||
const ActiveProviderEnv = "ZERO_PROVIDER"
|
||||
|
||||
// SetActiveProviderEnv exports the active provider name to the process environment
|
||||
// so a spawned child process (which inherits the environment) resolves the SAME
|
||||
// provider profile — and therefore the same credentials (env key / stored key /
|
||||
// OAuth) — as its parent. Without this a sub-agent re-resolves config.json's
|
||||
// default provider and can land on one whose credentials don't match the parent's
|
||||
// live selection, failing auth the instant it spawns. A blank name CLEARS the
|
||||
// variable: switching back to an unnamed/default profile must not keep exporting a
|
||||
// stale provider to children.
|
||||
func SetActiveProviderEnv(name string) {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
_ = os.Unsetenv(ActiveProviderEnv)
|
||||
return
|
||||
}
|
||||
_ = os.Setenv(ActiveProviderEnv, name)
|
||||
}
|
||||
|
||||
func applyEnv(cfg *FileConfig, env map[string]string) {
|
||||
activeProvider := strings.TrimSpace(envValue(env, "ZERO_PROVIDER"))
|
||||
activeProvider := strings.TrimSpace(envValue(env, ActiveProviderEnv))
|
||||
if activeProvider != "" {
|
||||
cfg.ActiveProvider = activeProvider
|
||||
}
|
||||
|
||||
@@ -441,6 +441,8 @@ func (m model) handleModelCommand(args string) (model, string) {
|
||||
m.providerProfile = nextProfile
|
||||
m.provider = nextProvider
|
||||
m.providerName = displayValue(nextProfile.Name, string(metadata.ProviderKind))
|
||||
// Keep sub-agent child processes on the same provider we just switched to.
|
||||
config.SetActiveProviderEnv(nextProfile.Name)
|
||||
m.modelName = target.modelID
|
||||
resetEffort := false
|
||||
if m.reasoningEffort != "" && !reasoningEffortAllowed(target.reasoningEfforts, m.reasoningEffort) {
|
||||
@@ -516,6 +518,8 @@ func (m model) switchProviderModel(providerName, modelID string) (model, string)
|
||||
m.providerProfile = target
|
||||
m.providerName = target.Name
|
||||
m.modelName = target.Model
|
||||
// Keep sub-agent child processes on the same provider we just switched to.
|
||||
config.SetActiveProviderEnv(target.Name)
|
||||
if strings.TrimSpace(m.userConfigPath) != "" {
|
||||
_, _ = config.SetActiveProvider(m.userConfigPath, target.Name)
|
||||
_, _ = config.SetProviderModel(m.userConfigPath, target.Name, target.Model)
|
||||
|
||||
Reference in new issue
Block a user