diff --git a/CHANGELOG.md b/CHANGELOG.md index 13bb749..f85e89a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,16 @@ All notable changes to `@krawlerhq/agent` land here. Format follows [Keep a Chan Nothing queued yet. -## [0.12.12] - 2026-04-21 +## [0.12.13] - 2026-04-22 + +### Fixed + +- **`saveConfig()` no longer wipes shared-keys.json with empty defaults.** When a caller passed a full `Config` object through `saveConfig` (notably the `loadConfig()` fresh-install branch, which parses schema defaults like `anthropicApiKey: ''`), every empty-string shared-key field was routed into `saveSharedKeys`, overwriting any keys the user had already pasted. Now empty-string shared-key values are filtered out of the split; callers that legitimately need to clear a key should call `saveSharedKeys` directly. Users upgrading from 0.12.12 or earlier whose keys vanished after a `config.json` reset will stop losing them. + +### Changed + +- **OpenRouter provider option now reads just "OpenRouter".** The old `OpenRouter (100s of models)` label was both misleading (the dropdown is a curated top 10 as of 0.12.12) and noisy in the provider ` - ${f.existing ? `
currently: ${f.existing} \u00b7 leave blank to keep
` : ''} + ${f.existing ? `
currently: ${f.existing} \u00b7 leave blank to keep, paste a new one to replace
` : ''} `).join(''); const providerOptions = PROVIDERS @@ -107,8 +110,11 @@ function renderPage(existing: SharedKeys, activeProvider: Provider, activeModel: .sub { color: var(--text-2); font-size: 0.95rem; margin: 0 0 32px; line-height: 1.55; } .row { margin-bottom: 22px; } .row:last-child { margin-bottom: 0; } - label { display: block; font-weight: 600; font-size: 0.82rem; margin-bottom: 6px; color: var(--text-2); } + label { display: flex; align-items: center; gap: 10px; font-weight: 600; font-size: 0.82rem; margin-bottom: 6px; color: var(--text-2); } + .badge-set { display: inline-flex; align-items: center; font-size: 0.68rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: #065f46; background: #d1fae5; border: 1px solid #a7f3d0; padding: 1px 8px; border-radius: 9999px; line-height: 1.4; font-family: -apple-system, system-ui, "Segoe UI", Roboto, sans-serif; } input[type=password], input[type=text], input[type=url], select { width: 100%; padding: 11px 14px; border: 1px solid var(--border); border-radius: 10px; font: inherit; font-size: 0.95rem; background: var(--surface); font-family: var(--mono); color: var(--text); } + .row.is-set input[type=password], .row.is-set input[type=text], .row.is-set input[type=url] { border-color: #6ee7b7; background: #f0fdf4; } + .row.is-set input:focus { border-color: var(--brand); background: var(--surface); } select { cursor: pointer; appearance: none; background-image: url("data:image/svg+xml;utf8,"); background-repeat: no-repeat; background-position: right 14px center; padding-right: 36px; } input:focus, select:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px rgba(37,99,235,0.18); } .section { padding-top: 28px; margin-top: 28px; border-top: 1px solid var(--border); } @@ -372,7 +378,7 @@ function providerLabel(p: Provider): string { case 'anthropic': return 'Anthropic'; case 'openai': return 'OpenAI'; case 'google': return 'Google'; - case 'openrouter': return 'OpenRouter (100s of models)'; + case 'openrouter': return 'OpenRouter'; case 'ollama': return 'Ollama (local)'; } }