feat: show update-available indicator in TUI footer#175
Conversation
🤖 Behavioral Analysis — 3 Finding(s)🟡 Warnings (2)
🔵 Nits (1)
Analysis run | Powered by QA Autopilot |
✅ Tests — All PassedTypeScript — passedPython — passedTested at |
Add a persistent, subtle upgrade indicator in both the home page and session footers. When a newer version of Altimate Code is available, the footer shows `current → latest · altimate upgrade` in muted/accent colors instead of just the version number. - Add `UpgradeIndicator` component and `getAvailableVersion` utility - Store available version in KV on `UpdateAvailable` event for persistence - Show indicator in both home and session footers - Fix toast message to say `altimate upgrade` instead of `opencode upgrade` - Add 24 tests covering version comparison, KV integration, and event flow Closes #173 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- F1: Clear KV on `Updated` event — set `update_available_version` to current `VERSION` after autoupgrade so indicator hides immediately - F2: Add semver comparison via `isNewer()` — prevents downgrade arrow when user upgrades externally past the stored version - F3: Reject empty string as invalid version in `getAvailableVersion()` - Update tests to cover all three fixes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
e18c645 to
1b86aff
Compare
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughPersist upgrade-related version info to the KV store on update events, add utilities to resolve whether a stored version is newer, introduce an UpgradeIndicator SolidJS component that reads KV to conditionally show an inline footer hint, and add tests covering utilities, KV integration, and event-driven flows. Changes
Sequence Diagram(s)sequenceDiagram
participant Installation as Installation Events
participant KV as KV Store
participant Indicator as UpgradeIndicator
participant UI as Footer UI
Installation->>KV: UpdateAvailable event\nkv.set(UPGRADE_KV_KEY, version)
Note over KV: Stored version for indicator
Indicator->>KV: mount / read\nkv.get(UPGRADE_KV_KEY)
KV-->>Indicator: stored version
Indicator->>Indicator: getAvailableVersion(stored, Installation.VERSION)
alt stored is newer
Indicator->>UI: render inline hint (available version)
else not newer or invalid
Indicator->>UI: render fallback / nothing
end
Installation->>KV: Updated event\nkv.set(UPGRADE_KV_KEY, Installation.VERSION)
Indicator->>KV: re-read value
KV-->>Indicator: current version
Indicator->>UI: clear hint
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
packages/opencode/src/cli/cmd/tui/app.tsx (1)
845-856: UseUPGRADE_KV_KEYhere to avoid key drift.At Line 845 and Line 855, the raw key string is duplicated. Reusing the shared constant prevents subtle regressions if the key ever changes.
Proposed fix
+import { UPGRADE_KV_KEY } from "./component/upgrade-indicator-utils" ... - kv.set("update_available_version", evt.properties.version) + kv.set(UPGRADE_KV_KEY, evt.properties.version) ... - kv.set("update_available_version", Installation.VERSION) + kv.set(UPGRADE_KV_KEY, Installation.VERSION)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/opencode/src/cli/cmd/tui/app.tsx` around lines 845 - 856, Replace the hard-coded key "update_available_version" with the shared constant UPGRADE_KV_KEY in both kv.set calls so the key cannot drift; update the two occurrences inside the event handlers (the handler that uses evt.properties.version and the sdk.event.on(Installation.Event.Updated.type, ...) handler that sets Installation.VERSION) to call kv.set(UPGRADE_KV_KEY, ...) and ensure UPGRADE_KV_KEY is imported or defined in this module.packages/opencode/test/cli/tui/upgrade-indicator.test.ts (1)
41-45: This assertion is non-informative and always passes.At Line 44, the condition matches the function’s declared return type, so it doesn’t verify behavior.
Proposed fix
- test("returns version when stored version is newer or unparseable (dev mode)", () => { - // In dev mode VERSION="local", semver parsing falls back to showing indicator - const result = getAvailableVersion("999.0.0") - expect(typeof result === "string" || result === undefined).toBe(true) - }) + test("returns version for high semver unless current version is non-comparable policy override", () => { + const result = getAvailableVersion("999.0.0") + if (Installation.VERSION === "local") { + expect(result).toBe("999.0.0") + } else { + expect(result).toBe("999.0.0") + } + })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/opencode/test/cli/tui/upgrade-indicator.test.ts` around lines 41 - 45, The test's assertion is too broad and always passes; update the assertion to assert the specific expected behavior of getAvailableVersion in dev mode by checking it returns the stored version string. Replace the current expect with a concrete check such as expect(result).toBe("999.0.0") (or at minimum expect(result).toBeDefined() and expect(typeof result).toBe("string")) so the test for getAvailableVersion("999.0.0") actually validates the function returns the version string in dev mode.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/opencode/src/cli/cmd/tui/component/upgrade-indicator-utils.ts`:
- Line 10: The isNewer function currently treats any parse failure as "newer"
(c.some(isNaN) || cur.some(isNaN) => true); change this so unparseable candidate
versions are rejected: if the parsed candidate parts contain NaN, return false
(not newer); similarly ensure the parsed current version is valid before
comparing—only perform numeric comparisons when both c and cur arrays have no
NaN. Apply the same validation/early-return logic to the KV parsing block
referenced around lines 20-24 so malformed KV strings do not result in a bogus
upgrade indicator.
---
Nitpick comments:
In `@packages/opencode/src/cli/cmd/tui/app.tsx`:
- Around line 845-856: Replace the hard-coded key "update_available_version"
with the shared constant UPGRADE_KV_KEY in both kv.set calls so the key cannot
drift; update the two occurrences inside the event handlers (the handler that
uses evt.properties.version and the
sdk.event.on(Installation.Event.Updated.type, ...) handler that sets
Installation.VERSION) to call kv.set(UPGRADE_KV_KEY, ...) and ensure
UPGRADE_KV_KEY is imported or defined in this module.
In `@packages/opencode/test/cli/tui/upgrade-indicator.test.ts`:
- Around line 41-45: The test's assertion is too broad and always passes; update
the assertion to assert the specific expected behavior of getAvailableVersion in
dev mode by checking it returns the stored version string. Replace the current
expect with a concrete check such as expect(result).toBe("999.0.0") (or at
minimum expect(result).toBeDefined() and expect(typeof result).toBe("string"))
so the test for getAvailableVersion("999.0.0") actually validates the function
returns the version string in dev mode.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 1e2c75b9-953f-44f5-b1c2-f47f00061b8e
📒 Files selected for processing (7)
packages/opencode/src/cli/cmd/tui/app.tsxpackages/opencode/src/cli/cmd/tui/component/upgrade-indicator-utils.tspackages/opencode/src/cli/cmd/tui/component/upgrade-indicator.tsxpackages/opencode/src/cli/cmd/tui/routes/home.tsxpackages/opencode/src/cli/cmd/tui/routes/session/footer.tsxpackages/opencode/test/cli/tui/upgrade-indicator.test.tspackages/opencode/test/cli/upgrade-notify.test.ts
packages/opencode/src/cli/cmd/tui/component/upgrade-indicator-utils.ts
Outdated
Show resolved
Hide resolved
- Replace custom `isNewer` with `semver.gt()` — `semver` is already a dependency; handles prerelease tags and rejects corrupted KV values - Use `UPGRADE_KV_KEY` constant in `app.tsx` instead of magic string - Add `fallback` prop to `UpgradeIndicator` — eliminates duplicate `getAvailableVersion` call in `home.tsx` (Gemini design suggestion) - Remove unused `UPGRADE_KV_KEY` re-export from `upgrade-indicator.tsx` - Add conditional check before `kv.set` on `Updated` event to avoid unnecessary file writes - Fix tautological test, add tests for corrupted/prerelease versions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 21 end-to-end tests covering the full upgrade indicator flow: - Full lifecycle: fresh install → UpdateAvailable → indicator shown → Updated → indicator hidden - F1 regression: stale indicator after autoupgrade is cleared - F2 regression: downgrade arrow prevention with `semver.gt()` - F3 regression: empty/corrupted/non-string KV values rejected - Semver integration: prerelease, build metadata, v-prefix handling - Edge cases: rapid events, Updated without UpdateAvailable, same version available as current Uses mock KV store pattern consistent with codebase test conventions (algorithm extraction, no Solid.js context required). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Change "available" to "update available" so users clearly understand a new version upgrade is pending, not just that a version exists. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On narrow terminals (<100 cols), hide "update available ·" text and show only the essential: ↑ 0.6.0 altimate upgrade Wide (100+): ↑ 0.6.0 update available · altimate upgrade Narrow (<100): ↑ 0.6.0 altimate upgrade Uses useTerminalDimensions() for reactive width detection. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
What does this PR do?
Adds a persistent, subtle upgrade indicator in the TUI footer that shows when a newer version of Altimate Code is available. Instead of relying only on a 10-second toast notification, users now see a persistent inline hint in both the home page and session footers:
When no update is available, the footer shows the current version as before.
Changes:
UpgradeIndicatorSolid.js component with muted/accent stylinggetAvailableVersionutility (pure function, easily testable)UpdateAvailableevent for persistence across route changesaltimate upgradeinstead ofopencode upgradeType of change
Issue for this PR
Closes #173
How did you verify your code works?
kv.jsonwith{"update_available_version":"0.5.0"}and launching the TUIInstallation.VERSIONChecklist
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests