Release 0.10.0-beta.1: migration framework + credential layer + SDK routing + update banner#174
Merged
luokerenx4 merged 7 commits intomasterfrom May 9, 2026
Merged
Release 0.10.0-beta.1: migration framework + credential layer + SDK routing + update banner#174luokerenx4 merged 7 commits intomasterfrom
luokerenx4 merged 7 commits intomasterfrom
Conversation
…s, PnL color discipline, live-pulse indicator, Portfolio polish Lifts the rest of the app to the polish bar set by the recent UTA pages redesign (commit b0b79ba). No new pages, no behavioural changes — only visual / design-system gaps. **Typography scale (index.css)** - New semantic classes `.text-display` (28-36) `.text-title` (16) `.text-body` (13) `.text-caption` (12) `.text-micro` (11). New code should opt into these instead of inventing arbitrary `text-[Npx]` values. **LiveIndicator + PageHeader live prop** - New `<LiveIndicator>` — small breathing green dot + "updated Xs ago" microcopy that ticks every 5s on its own - `<PageHeader live={{ lastUpdated }}>` opt-in renders the dot next to the title and the relative time in the description row - Wired into TradingPage / UTADetailPage / PortfolioPage. New `@keyframes live-pulse` defines the breathing motion (2.4s cycle — ambient, not anxious) **PnL color discipline** - Replaced `text-green-400` / `text-emerald-*` / `text-red-400` / `bg-red-500` etc. with semantic tokens (`text-green` / `text-red` / `bg-red`) across PushApprovalPanel, ContextMenu, ChatMessage, ChatChannelList, ChatChannelListContainer, DevPage, MarketSidebar, market/QuoteHeader/SearchBox/{Profile,KeyMetrics,FinancialStatements, TradeableContracts}Panel, NotificationsInboxPage. Three green shades collapsed to one; categorical asset-class chips that previously used emerald now share the canonical green token. **lucide-react (high-traffic icons)** - Added `lucide-react` dependency - ActivityBar's 9 nav icons replaced with lucide equivalents (MessageSquare, LineChart, GitBranch, BarChart3, Newspaper, Notebook, Zap, Settings, Code2). Removed the inline `INDICATOR_STYLE` constant with hardcoded `#58a6ff` — active indicator now uses `bg-accent`. - TabStrip × button + ChatChannelList settings/delete buttons swapped for `<X>` and `<Settings>` from lucide. Smaller files, consistent stroke weights, future icon adds become trivial. - In-page custom SVGs (in market panels, dialogs, etc.) deferred to later passes; this PR only touches the always-visible shell. **Portfolio page polish** - Hero now uses the shared `<Metric>` component with today PnL delta arrow (▲/▼ + sign-colored percent), same primitive as TradingPage - Per-account `<Sparkline>` on each card in AccountStrip — 24h trend at a glance per UTA - AccountStrip rebuilt as 2-column card grid (was inline chips); each card shows label · NLV · today PnL · sparkline - Inlined fmt/fmtPnl/fmtNum helpers replaced with imports from `lib/format` (DRY with TradingPage / UTADetailPage) - Page-level live indicator wired in via the new PageHeader prop No backend changes. No test changes (all 1520 still passing). Vite build clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… credentials as 0002 Drizzle-style framework: journal-based runner (data/config/_meta.json), per-migration data/_backup snapshots, static registry (asar-safe). 0001 folds the four ad-hoc loadConfig() ifblocks into one idempotent migration; ifblocks deleted. 0002 extracts apiKey/baseUrl into a top-level credentials map — profiles gain credentialSlug, inline fields kept as transitional fallback. resolveProfile() joins on read; ResolvedProfile shape unchanged so providers don't change. Build-time INDEX.md generator wired to prebuild — PR diffs surface migration additions explicitly. Foundation for vendor-shaped preset catalog and non-chat LLM utilities. Out of scope: preset reshape, /api/config/credentials CRUD, update notification UI, Electron auto-update. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Each preset now declares the SDK adapters its credential can drive, with explicit per-adapter config builders that map credential fields into each SDK's standardized config (vercel uses baseURL, agent-sdk uses baseUrl — no normalization, the preset spells it out). Test path goes through the preset's declared `test` adapter, falling back to honoring profile.backend for Custom/legacy profiles. Light presets (Claude API, OpenAI API, Gemini, MiniMax, GLM, Kimi, DeepSeek) now skip the agent-sdk subprocess entirely and run a bare-minimum generateText call via @ai-sdk/anthropic|openai|google. Per-vendor baseURL quirk: MiniMax/GLM/Kimi serve Anthropic API at `/anthropic/v1/messages`; their config builder appends `/v1` to the user's baseUrl. DeepSeek serves at `/anthropic/messages`; its builder passes baseUrl through unchanged. Verified end-to-end with real credentials for MiniMax (~7s) + DeepSeek (~2s). Subscription presets (Claude OAuth, Codex OAuth) keep agent-sdk/codex as their test adapter — the heavy harness is physically required. Chat path unchanged this round (still routes via profile.backend). Foundation for chat path going preset-driven in a future plan. 42 new tests cover preset declarations, vendor-inference round-trip, adapter dispatch (mocked SDK imports), fallback synthesis for Custom. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…irectional highlight Page rebuild from "flat profile list" to "credentials (left, editable) + available SDKs (right, read-only)". Profiles nest inside their credential card. Clicking either side dims incompatible cards on the other — bidirectional discovery of the credential ↔ SDK relationship. Backend changes that the new UI depends on: - writeProfile now eagerly extracts credentials: new profiles land with credentialSlug + a (possibly deduped) entry in the credentials map. Same-vendor/auth/apiKey/baseUrl reuses an existing slug. - deleteProfile garbage-collects orphaned credentials when the last referencing profile is removed. - 0003_backfill_credentials migration cleans up profiles added between 0002 landing and writeProfile going eager (e.g. user's DeepSeek). - SDK_ADAPTER_LABELS map + getSdkAdapterInfo() helper computes human-readable adapter info from PRESET_CATALOG; surfaced via new GET /api/config/sdk-adapters endpoint. /profiles response gains a `credentials` field so one fetch covers everything the page needs. Frontend: - Two new components: CredentialCard (collapsible, profile rows nested) and SdkAdapterCard (read-only, lists compatible presets with solid/hollow dots for configured/unconfigured). - Selection state in the page drives dim logic: clicking a credential dims SDKs not in its preset's available list; clicking an SDK dims credentials whose preset doesn't register that SDK. 15 new tests (extractCredentialFromProfile dedup + slug generation, 0003 backfill + idempotency, getSdkAdapterInfo shape). Out of scope: credential CRUD HTTP endpoints, wizard refactor to "credential first" two-step, removing inline credential fields from profileSchema, chat path going preset-driven. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
App now polls GitHub Releases for newer versions and surfaces them as a top-of-app banner. Self-hosted source distribution: when user sees the banner, they manually run \`git pull && pnpm build\` and restart. Auto-execute is out of scope (Electron auto-update will handle that path natively when packaging lands). Backend (\`src/core/version.ts\`): - getCurrentVersion reads package.json#version at module load - getRepoSlug parses owner/repo from package.json#repository.url so fork users don't poll the upstream repo - fetchLatestRelease hits GitHub Releases API with TTL cache (1h on success, 5min on error) — keeps us under the 60 req/h unauthenticated rate limit even if many UI tabs poll - compareVersions handles MAJOR.MINOR.PATCH plus prerelease suffix (release > prerelease for same core; lex compare among prereleases) - New GET /api/version endpoint returns the combined VersionInfo Frontend: - UpdateBanner: shown when hasUpdate=true; "Release notes" link to GitHub, "Skip this version" persists in localStorage so the user isn't bugged about the same version twice, "×" dismisses for the current session only - Wired into AppShell as a top row above the activity bar + main panel — only takes vertical space when a banner is actually showing 14 new tests cover compare, cache, fetch error paths, hasUpdate computation. Two follow-up TODO items added for native Anthropic / OpenAI Chat Completions full providers (deferred — much bigger scope than test-path swap). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… surface GitHub's /releases/latest endpoint silently excludes any release flagged as prerelease — so a project shipping only -beta.X tags would always get 404 and the update banner would never trigger. Switch to /releases (returns all in published_at desc), skip drafts explicitly, take the first. Confirmed against TraderAlice/OpenAlice: now picks up v0.10.0-beta.0 correctly. Tests updated to mock the array shape; +3 cases for draft-skip / prerelease-acceptance / empty-list error path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Highlights of this beta: - Versioned migration framework (Drizzle-style journal + per-migration snapshots, INDEX.md auto-generated from registry metadata). - Credential layer split out from profiles — vendor + auth as a first-class stored concept; profiles point in via credentialSlug. - Preset-driven SDK adapter selection: every preset declares which SDK adapters its credential can drive plus a `test` default; test path goes light (vercel-anthropic / codex / vercel-google) instead of always spawning a Claude Code subprocess. - AI Provider page rebuild — credentials column (editable, profiles nested inside) + SDKs column (read-only, lists compatible presets with bidirectional click-to-highlight). - GitHub Releases update detection + top-of-app banner with "skip this version" / "release notes" / session-dismiss. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR introduces the migration / version-awareness substrate the
project was missing, decouples the AI credential layer from SDK
implementation choice, and ships an update-notification banner — all
foundation for the Electron packaging that's coming next, but useful
on its own to anyone running OpenAlice from source today.
Headlines:
build-time INDEX.md.
first-class storage; profile points in via
credentialSlug).SDK adapters its credential can drive; the test path now uses the
lightest available (skipping the Claude Code subprocess for non-
subscription cases).
click-to-highlight.
0.10.0-beta.1.Per-session contributions
2026-05-09 — Migration framework + credential layer + SDK routing + update banner + 0.10.0-beta.1
src/migrations/): journal indata/config/_meta.json, per-migrationdata/_backup/{ts}-pre-{id}/snapshots, static registry (asar-safe), build-time INDEX.md
generator wired to
prebuild. The 5 historical ad-hoc migrationifblocks in
loadConfig()collapse into0001_initial_unified;0002_extract_credentialsintroduces the credentials map;0003_backfill_credentialscleans up stragglers.aiProviderSchema. Profile gainscredentialSlugpointer.resolveProfile()joins on read (inline fields kept as transitionalfallback).
writeProfileextracts eagerly with dedup;deleteProfileGCs orphaned credentials.sdkAdapters: { available: [{id, config: cred=>sdk-shaped}], test }.Preset's config builder spells out per-SDK field names explicitly
(vercel uses
baseURL, agent-sdk usesbaseUrl) so providers don'treverse-search credential fields. Light invokers (vercel-anthropic /
vercel-openai / vercel-google) skip tools + system prompt for
bare-minimum test-path round trips. Test on DeepSeek/MiniMax now
takes 1-7s (HTTP) instead of 5s+ (Claude Code subprocess spawn).
Credentialscolumn (editable, withprofiles nested as collapsible children) +
Available SDKscolumn(read-only, lists compatible presets with solid/hollow dots for
configured/unconfigured). Click either side to dim incompatible
cards on the other.
src/core/version.tsreadspackage.json#version, parses owner/repo from the repository field,hits GitHub Releases API with TTL cache (1h success / 5min error),
compares with semver.
GET /api/versionexposes the result.UpdateBannershows whenhasUpdate=truewith "Release notes →" /"Skip this version" / session-dismiss. Hits
/releases(not/releases/latest) so prerelease tags likev0.10.0-beta.0surface.Chat Completions full provider — bigger scope than the test-path
swap (parallel to
CodexProvidersize each), deferred.0.10.0-beta.0→0.10.0-beta.1.Key commits:
546a295,1afd316,740b548,cbc6a53,48f3354,c14ba5aFull commit log
Test plan
npx tsc --noEmitcleanpnpm testpasses (1592 tests, +88 new this session)data/config/migrates idempotently across reruns; backups land indata/_backup/vercel-anthropicend-to-end (verified with real credentials, ~2-7s)/api/versionreturnsv0.10.0-beta.0from GitHub Releases (post prerelease fix)hasUpdate=true, "Skip this version" persists in localStoragev0.10.0-beta.1appears on GitHub Releases page🤖 Generated with Claude Code