Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 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
e7ed6f1
fix(providers): scope credential deletion to owning row
PierrunoYT Sep 2, 2026
ebf8579
fix(providers): respect dictation credential claims
PierrunoYT Sep 3, 2026
806271a
Merge remote-tracking branch 'upstream/main' into pr1/provider-identi…
ampagent Sep 7, 2026
0411bf0
fix(providers): preserve legacy merges and reject cross-layer mutations
ampagent Sep 7, 2026
3ecbda3
Merge refreshed provider identity base into catalog ownership stack
ampagent Sep 7, 2026
8048208
Merge upstream main into provider identity primitives
ampagent Sep 12, 2026
daf502f
Merge refreshed provider identity base into catalog ownership stack
ampagent Sep 12, 2026
8427853
fix(config): distinguish blocked provider paths from missing config
ampagent Sep 12, 2026
749a3dd
Merge Windows provider-path classification fix from identity base
ampagent Sep 12, 2026
78110c9
fix(providers): preserve identity across repair and session mutations
PierrunoYT Sep 13, 2026
b906276
fix(tui): replace stale removed provider identity
roomote Sep 14, 2026
6b4a190
test(tui): model removed provider fixture
roomote Sep 14, 2026
8673a02
Merge corrected provider identity foundation into PR 2
roomote Sep 14, 2026
e218202
Merge current main and isolate provider ownership test fixtures
PierrunoYT Sep 19, 2026
0cd714e
Merge current upstream main into provider identity primitives
ampagent Sep 19, 2026
f187303
fix(tui): release retained provider identity on session resume
ampagent Sep 19, 2026
e13f6e8
Merge refreshed provider identity foundation into catalog ownership
ampagent Sep 19, 2026
dff3fbf
fix(tui): reconcile stored-key markers after manager deletion
ampagent Sep 20, 2026
010ccd8
Merge provider-manager key reconciliation into catalog ownership
ampagent Sep 20, 2026
83fa9eb
fix: preserve live provider identity across session resume
ampagent Sep 25, 2026
808af63
fix(cli): prioritize concrete provider rows over catalog aliases
ampagent Sep 25, 2026
a536157
Merge remote-tracking branch 'review/pr892' into review/pr893-refreshed
ampagent Sep 26, 2026
b0bab4b
test(tui): isolate manager OAuth credential probes
ampagent Sep 28, 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 legacy effective provider and active reference; identity-changing repairs of stored-key profiles refuse before writing, so they cannot point at another credential

### 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.9.0](https://github.com/Gitlawb/zero/compare/v0.8.0...v0.9.0) (2026-09-15)


Expand Down Expand Up @@ -81,7 +91,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
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ 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`). If a row already has that
exact name, the command preserves the field merge older releases used, with
later nonempty fields taking precedence. An explicit `--name <unique-name>`
keeps the legacy row separate instead. Case-only collisions and multiple
unnamed rows are not merged by guessing; follow the error's repair guidance.

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

Expand Down Expand Up @@ -307,7 +315,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
10 changes: 9 additions & 1 deletion README_ZH.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ zero models list
zero doctor
```

如果升级后的 `config.json` 中有一个旧版未命名的提供商配置,请运行
`zero providers repair-config` 进行修复。该命令会保留已保存的
`activeProvider` 名称(未设置时回退到 `openai`)。如果已有配置行使用完全相同的
名称,该命令会保留旧版本的字段合并规则,后出现的非空字段优先。
通过 `--name <唯一名称>` 显式指定名称则会将旧配置行单独保留。
对于仅大小写不同的名称冲突或多个未命名的配置行,Zero 不会猜测并合并;
请按照错误消息中的修复指引操作。

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

```bash
Expand Down Expand Up @@ -212,7 +220,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 @@ -545,6 +548,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 @@ -404,6 +404,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