Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
733cc18
fix(config): define provider identity primitives and duplicate-name v…
PierrunoYT Aug 12, 2026
00b9e87
test(config): cover case-variant upsert rejection
ampagent Aug 12, 2026
7b30aaf
fix provider identity lifecycle boundaries
PierrunoYT Aug 12, 2026
e709787
fix: address provider review feedback
PierrunoYT Aug 12, 2026
82243d3
fix: serialize provider credential updates
PierrunoYT Aug 13, 2026
88cc2fb
fix(config): keep provider transaction out of identity slice
PierrunoYT Aug 14, 2026
4380999
fix(provider): finish the identity contract at every consumer boundary
PierrunoYT Aug 16, 2026
a3b18f5
fix(provider): address CodeRabbit review on the identity contract
PierrunoYT Aug 16, 2026
55f6b48
fix(tui): reconcile live session, saved list, and disk on one rule
PierrunoYT Aug 17, 2026
c3f1f6d
fix(provider): close remaining identity review findings
ampagent Aug 18, 2026
35fe02a
fix(provider): preserve legacy config and OAuth state
PierrunoYT Aug 20, 2026
89b0c6e
docs(provider): document config repair and OAuth validation
PierrunoYT Aug 21, 2026
72d3ea6
fix(provider): make legacy config repairs composable
PierrunoYT Aug 21, 2026
f4a9449
fix(provider): use user-scoped credential store
PierrunoYT Aug 21, 2026
9fc1c03
test(provider): resolve credential lock path portably
PierrunoYT Aug 21, 2026
2b8faf3
fix(config): migrate repaired active provider
PierrunoYT Aug 22, 2026
5ad69c0
fix(provider): resolve identity ownership before mutating persisted rows
PierrunoYT Aug 23, 2026
9d9cf60
feat(providers): resolve catalog ownership and credential candidates
PierrunoYT Aug 12, 2026
c64767b
fix(providers): address credential identity review findings
ampagent Aug 12, 2026
a5c0405
fix(config): fail closed on ambiguous folded provider names
PierrunoYT Aug 14, 2026
028ae99
fix(providers): close remaining credential review gaps
ampagent Aug 18, 2026
3a25e23
fix(provider): fail closed on ambiguous identities
PierrunoYT Aug 21, 2026
84b3fcd
fix(provider): close remaining identity ambiguities
PierrunoYT Aug 21, 2026
0160257
fix(config): adopt legacy catalog-named rows on login
PierrunoYT Aug 23, 2026
542c223
fix(config): bind credential publication to config path
ampagent Aug 27, 2026
9598b0e
fix provider credential review findings
ampagent Aug 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
aims to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html) once the first release is
tagged. Until then, source builds report the version `dev`.

## Unreleased

### Features

* **providers:** add `zero providers repair-config [--name <name>]` to recover a single legacy unnamed provider profile while preserving the active-provider name or falling back to `openai`

### Bug Fixes

* **oauth:** validate provider configuration before authorization and immediately before token replacement across CLI, TUI, setup, and device flows, preserving existing credentials when validation fails

## [0.8.0](https://github.com/Gitlawb/zero/compare/v0.7.0...v0.8.0) (2026-08-21)


Expand All @@ -26,7 +36,6 @@ tagged. Until then, source builds report the version `dev`.
* **modelregistry:** expose reasoning effort for DeepSeek V4 models ([#931](https://github.com/Gitlawb/zero/issues/931)) ([90dcfd1](https://github.com/Gitlawb/zero/commit/90dcfd127e8a6d9902ec9f4e72f6d03fef1a0fc6))
* **providers:** discover ChatGPT capabilities ([#890](https://github.com/Gitlawb/zero/issues/890)) ([2d2450e](https://github.com/Gitlawb/zero/commit/2d2450e9a744349f0d01b1d4e9ba29c24ba5650d))
* **sandbox:** normalize launcher names before the command-prefix denylist ([#934](https://github.com/Gitlawb/zero/issues/934)) ([6edf9a8](https://github.com/Gitlawb/zero/commit/6edf9a8b78dc030dc44598919db1c7fa9d4f809a))

## [0.7.0](https://github.com/Gitlawb/zero/compare/v0.6.0...v0.7.0) (2026-08-10)


Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ zero models list
zero doctor
```

If an upgraded `config.json` contains one legacy provider profile without a
name, repair it with `zero providers repair-config`. The command preserves the
saved `activeProvider` name (falling back to `openai`), or accepts an explicit
replacement with `--name <name>`. Multiple unnamed rows are not guessed; repair
those directly in `config.json`.

For API providers, set the matching environment variable before setup or enter
the key in the wizard:

Expand Down Expand Up @@ -290,7 +296,7 @@ zero exec one-shot or scripted agent run
zero setup first-run provider setup
zero auth OAuth/login helpers for supported providers
zero models model registry and capabilities
zero providers provider profiles and detection
zero providers provider profiles, recovery, and detection
zero doctor setup, key, and connectivity checks
zero context context-budget report
zero repo-map deterministic repository map
Expand Down
8 changes: 7 additions & 1 deletion README_ZH.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ zero models list
zero doctor
```

如果升级后的 `config.json` 中有一个旧版未命名的提供商配置,请运行
`zero providers repair-config` 进行修复。该命令会保留已保存的
`activeProvider` 名称(未设置时回退到 `openai`),也可以通过
`--name <名称>` 显式指定新名称。对于多个未命名的配置行,Zero 不会猜测,
请直接在 `config.json` 中修复。

对于 API 提供商,在设置之前设置匹配的环境变量或在向导中输入密钥:

```bash
Expand Down Expand Up @@ -208,7 +214,7 @@ zero exec 一次性或脚本化智能体运行
zero setup 首次运行提供商设置
zero auth 支持提供商的 OAuth/登录辅助
zero models 模型注册表和能力
zero providers 提供商配置和检测
zero providers 提供商配置、修复和检测
zero doctor 设置、密钥和连接检查
zero context 上下文预算报告
zero repo-map 确定性仓库映射
Expand Down
7 changes: 7 additions & 0 deletions docs/oauth-subscriptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ When a login exists for a provider, the **OpenAI and Anthropic** providers send
before. Tokens are stored 0600 (or the OS keyring with
`ZERO_OAUTH_STORAGE=keyring`) and never logged. See `zero auth --help`.

Provider OAuth login validates the persisted user configuration before opening
authorization and revalidates it immediately before replacing a stored token.
This applies to CLI login, the TUI/setup wizard, and device-code completion. If
the configuration is invalid at either check, Zero aborts without overwriting
the previous OAuth credential. If the error identifies one legacy unnamed
provider profile, repair it with `zero providers repair-config`.

### In the setup wizard (`/provider`)

Running `/provider` opens a **"How do you want to connect?"** chooser:
Expand Down
6 changes: 6 additions & 0 deletions internal/cli/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/Gitlawb/zero/internal/localcontrol"
"github.com/Gitlawb/zero/internal/mcp"
"github.com/Gitlawb/zero/internal/modelregistry"
"github.com/Gitlawb/zero/internal/oauth"
"github.com/Gitlawb/zero/internal/observability"
"github.com/Gitlawb/zero/internal/peermsg"
"github.com/Gitlawb/zero/internal/plugins"
Expand Down Expand Up @@ -69,6 +70,7 @@ type appDeps struct {
discoverProviderModels func(context.Context, config.ProviderProfile) ([]providermodeldiscovery.Model, error)
detectLocalRuntimes func(context.Context, provideronboarding.LocalDetectOptions) []provideronboarding.DetectedLocalRuntime
openRouterLogin func(context.Context, provideroauth.OpenRouterOptions) (string, error)
chatGPTLogin func(context.Context, provideroauth.ChatGPTOptions) (oauth.Token, error)
newSessionStore func() *sessions.Store
loadPlugins func(plugins.LoadOptions) (plugins.LoadResult, error)
loadHooks func(hooks.LoadOptions) (hooks.LoadResult, error)
Expand Down Expand Up @@ -172,6 +174,7 @@ func defaultAppDeps() appDeps {
discoverProviderModels: defaultDiscoverProviderModels,
detectLocalRuntimes: provideronboarding.DetectLocalRuntimes,
openRouterLogin: provideroauth.OpenRouterLogin,
chatGPTLogin: provideroauth.ChatGPTLogin,
newSessionStore: func() *sessions.Store {
return sessions.NewStore(sessions.StoreOptions{})
},
Expand Down Expand Up @@ -552,6 +555,9 @@ func fillAppDeps(deps appDeps) appDeps {
if deps.openRouterLogin == nil {
deps.openRouterLogin = defaults.openRouterLogin
}
if deps.chatGPTLogin == nil {
deps.chatGPTLogin = defaults.chatGPTLogin
}
if deps.newSessionStore == nil {
deps.newSessionStore = defaults.newSessionStore
}
Expand Down
21 changes: 21 additions & 0 deletions internal/cli/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,27 @@ func TestRunNoArgsFailsWhenResolveErrorIsNotProviderRelated(t *testing.T) {
}
}

func TestRunNoArgsOffersRepairCommandForPersistedNameFailure(t *testing.T) {
var stdout, stderr bytes.Buffer
cwd := t.TempDir()
configPath := filepath.Join(t.TempDir(), "zero", "config.json")
writeProviderOnboardingConfig(t, configPath, config.FileConfig{Providers: []config.ProviderProfile{{Name: ""}, {Name: "work"}, {Name: "WORK"}}})
exitCode := runWithDeps(nil, &stdout, &stderr, appDeps{
getwd: func() (string, error) { return cwd, nil },
userConfigPath: func() (string, error) { return configPath, nil },
resolveConfig: func(string, config.Overrides) (config.ResolvedConfig, error) {
return config.Resolve(config.ResolveOptions{UserConfigPath: configPath, Env: map[string]string{}})
},
runTUI: func(context.Context, tui.Options) int {
t.Fatal("TUI must not launch with ambiguous persisted identities")
return 0
},
})
if exitCode == exitSuccess || !strings.Contains(stderr.String(), "zero providers repair-config") {
t.Fatalf("exit=%d stderr=%q, want actionable repair path", exitCode, stderr.String())
}
}

func TestRunNoArgsLaunchesTUIWithMCPState(t *testing.T) {
var stdout bytes.Buffer
var stderr bytes.Buffer
Expand Down
Loading
Loading