VaultOne v1.8.0
Added
- Provider management: the provider list + CRUD — a new Providers top-level view (供应商) lists every saved provider (name / category / endpoint / model) with drag-to-reorder, plus an empty state that points to the upcoming preset picker. Create, edit and delete custom providers through a side-panel sheet (name / endpoint / API key); the API key and endpoint live inside the provider's
settingsConfigsnapshot, which the form preserves field-for-field. Data stays in a local SQLiteprovidertable for now — switching providers (live write), presets, sync, model mapping and JSON editing land in later tickets. - Switching a provider writes to live settings — the Providers view gains a Currently using card (active provider + endpoint + model) and a per-row Switch button. Switching merges the provider's snapshot into
~/.claude/settings.jsoncontrolled fields only (env+includeCoAuthoredBy/attribution/effortLevel/enabledPlugins/skipWebFetchPreflight), leaving everything else — hooks, MCP servers, permissions, plugins, model — untouched on disk; the previous live file is backed up tosettings.json.bak(single-file overwrite) before an atomic temp-file rename. The active provider is remembered in the localconfig.jsonand survives restarts. - 18 built-in provider presets — the Providers view now ships a preset picker (searchable, grouped by category) with 18 templates: Claude Official + AWS Bedrock ×2, eleven domestic vendors (Kimi, DeepSeek, GLM, Volcengine, DouBao, Baidu, Alibaba, StepFun, MiniMax, MiMo …) and four popular aggregators (SiliconFlow, OpenRouter, ModelScope, Novita). Picking one pre-fills the new-provider form with its endpoint / auth / model mapping; the preset itself is never mutated, so you can edit and save as a custom provider. Presets ship with the app — they never sync.
- Raw settings.json editor in the provider form — the provider sheet ends with a CodeMirror 6 JSON editor over the full snapshot: syntax highlighting, red underlines for parse errors or a non-object top level, a format button (2-space), and dark/light theme following. The JSON is the single source of truth — editing it re-derives the form's endpoint / API key, editing a field merges back, and an invalid snapshot blocks saving instead of silently discarding your edit.
- Provider structure syncs across devices — the provider list now rides the existing push/pull orchestration as a per-device
providers.jsonunderrepo/data/<deviceId>/: every push materializes this device's file from the local database (byte-stable, so an unchanged store pushes nothing), every pull merges all peers' files back by id with the newestupdated_atwinning. API keys never enter the sync file — the four secret env keys (ANTHROPIC_AUTH_TOKEN/ANTHROPIC_API_KEY/ the AWS key pair) are stripped before writing, and each device fills its own keys locally; importing a peer's key-stripped copy merges the local row's keys back in, so a keyless copy can never overwrite a filled one. The active provider stays local inconfig.json— activation never syncs. - Model role mapping with 1M marker — the provider form gains a five-role model map (Sonnet / Opus / Fable / Haiku / Subagent), each role with a display name, a request model, and a 1M-context checkbox (Haiku strips the marker automatically — it does not support 1M). Roles missing from a provider's config are back-filled when the provider loads, and the "apply to all" action spreads any filled-in model across every role in one click.
- Fetch model list — the model-map section's "fetch models" button pulls the vendor's OpenAI-compatible
/v1/modelsendpoint from the backend (the webview's fetch would hit CORS): an explicitmodelsUrloverride wins, a base URL ending in a version segment appends/modelsinstead of a second/v1, known Anthropic-compatible subpaths are stripped, and the candidates deduplicate to at most three tried in order. The returned model ids fill all five roles in one click; failures surface as bucketed toasts (auth failed / endpoint closed / timeout / unsupported format). - Common config snippet — a provider-independent settings snippet (default
{"includeCoAuthoredBy": false}to hide attribution) lives in the provider form: hand-write it, tick it enabled, and every switch merges it into the controlled fields only —envmerges deep by key with the provider's own values winning, other controlled switches are filled only when the provider hasn't set them, and non-controlled fields are never touched by it. - Auth field toggle + template variables — the form's auth field switches between
ANTHROPIC_AUTH_TOKENandANTHROPIC_API_KEY, moving the entered value across on toggle. Bedrock presets additionally surface template variables (region / access key / secret key) that are substituted recursively into${VAR}placeholders before saving; an unfilled variable blocks saving instead of writing a broken config. - Export / import providers — the full provider list can be exported as one JSON document (optionally including API keys) and imported back on any device: merge mode dedupes by id without touching existing rows, overwrite mode lets the imported copy win. A purely manual migration path — import goes to the local database only and never through git sync.
- Jump between user turns — opening a session now also mounts a slim panel beside the transcript listing every user message (width of ~16 Chinese characters, overflowing rows ellipsize). Click a row to jump straight to that message, the row for the message you're reading stays highlighted, and hovering any row shows its full text. The two panels open and close together.
- Jump flashes the target — clicking a turn in the nav panel rings the message it lands on with three quick pulses of the accent ring, so the eye arrives exactly where the scroll did.
Changed
-
Source parsers renamed to
SourceParser— the log-parser module (providers/) becomessource_parser/, freeing the word "Provider" for the upcoming vendor-management feature. Pure rename, no behavior change. -
Request-log table drops its duplicate Source columns — the two columns both derived from the same
sourcefield (a readable name with a stale "(Session)" suffix, and the raw tag) merge into one Source column: the readable name, with the raw tag on hover. The misleading suffix is gone — each row is a single API call, not a session. -
Long sessions open instantly — the transcript now renders through a virtualized list (react-virtuoso), keeping only the messages near the viewport in the DOM. A multi-thousand-message session no longer stalls while every row is laid out at once, and scrolling stays smooth regardless of length.
-
Message header rows mirror cleanly — on both the assistant and user voices the toolbar (collapse chevron + copy) and the time/model block are pinned to opposite ends of the bubble, so a short user message no longer crams the two together against the edge.
Fixed
- Turn jumps no longer overshoot — jumping scrolled smoothly past the target to an estimated position and glided back, visibly running to the bottom of the transcript before springing to the message. Jumps now land instantly, with the ring flash carrying the feedback.
- The 840×600 minimum window actually sticks now — the lightweight-mode restore commands were re-applying an old 720×520 floor via
set_min_size, silently overriding the raised minimum. The dashboard no longer restores undersized after a glance-card round-trip. - Sessions table no longer overlaps at narrow widths — the seven fixed columns squeezed the title column to zero and spilled the header into the Project column. The table now keeps a readable width and scrolls horizontally instead.