Skip to content

feat: flag when a newer Kagan release is available - #10

Merged
aorumbayev merged 1 commit into
mainfrom
update-banner
Jul 9, 2026
Merged

feat: flag when a newer Kagan release is available#10
aorumbayev merged 1 commit into
mainfrom
update-banner

Conversation

@aorumbayev

@aorumbayev aorumbayev commented Jul 9, 2026

Copy link
Copy Markdown
Member

Why

OpenCode installs a plugin once and caches it forever. It never re-checks npm, and re-running opencode plugin @kagan-sh/kagan reuses the same cache — so a user who installs Kagan is never told a newer version exists and has no obvious way to move to it. (Confirmed by reading the opencode plugin loader and npm cache: the resolved @latest spec is cached per exact string and short-circuits on subsequent loads; opencode upgrade doesn't touch the plugin cache either.)

What

  • src/update-check.ts — checks npm's dist-tags endpoint at most once a day, caching the result in api.kv across restarts. Pure, fully-injected logic:
    • parseRelease accepts only clean x.y.z releases; dev/prerelease builds (the repo's own 0.0.0-development, any -beta) return undefined, so local/dev installs never nag and a prerelease latest can't false-positive.
    • isNewerRelease compares segments numerically (0.1.10 > 0.1.3).
    • resolveLatestVersion keeps serving the cached value on a network failure without going dark for a day, and refetches if the stored timestamp is in the future (clock skew).
  • Board footer shows → vX.Y.Z available in the accent color when a newer release exists — always visible whenever the board is open, which is the only place Kagan lives.
  • The check fires once from the TUI entry (tui.tsx), off the render path, and can never crash or hang the board (short timeout + abort, all errors swallowed).
  • Docs (quickstart.md + README pointer) explain the two real ways to update: clear the cached package dir, or pin-and-bump the version.

Design notes

  • The network call lives in tui.tsx, not in the store — so no store/board unit test triggers a live npm request. The store just holds a signal; the board test drives the indicator via store.setUpdateAvailable(...).
  • I deliberately dropped an auto-dismissing toast: the check runs at opencode startup, so a 10s toast would almost always expire before the user opens the board. The persistent footer indicator is the reliable signal.

Testing

  • New test/update-check.test.ts: version-comparison edge cases, TTL/cache behavior, network-failure fallback, clock-skew refetch, dev-version skip.
  • Footer-render test in test/board.test.tsx.
  • bun run check (prettier + oxlint + tsc + 650 tests + package-check) passes clean.

Reviewed adversarially before opening (kv-ready timing, cache-path accuracy, network isolation in tests, version-compare correctness all verified against opencode source); no blockers or majors found.

@greptile-apps

greptile-apps Bot commented Jul 9, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds a cached update check and surfaces newer Kagan releases in the board footer. The main changes are:

  • Daily npm dist-tags lookup with KV-backed cache and network-failure fallback.
  • Stable release parsing and numeric version comparison for x.y.z versions.
  • TUI startup wiring that records newer releases in the board store.
  • Footer indicator showing → vX.Y.Z available when an update is available.
  • Quickstart and README guidance for updating OpenCode’s cached plugin install.
  • Tests for update-check behavior and footer rendering.

Confidence Score: 5/5

This PR is safe to merge with minimal risk.

The change is localized and follows the existing TUI/store separation. Tests cover parsing, version comparison, caching, fetch failures, malformed responses, clock skew, dev-version suppression, and footer rendering. No blocking logic or security issues were found.

No files require special attention.

T-Rex T-Rex Logs

What T-Rex did

  • Ran a focused Bun test suite for update-check and board UI tests, which completed with 31 passing and 0 failing tests.
  • Verified type correctness by running Bun typecheck, which finished with exit code 0.
  • Captured a standalone OpenTUI component harness showing before/after Board frames to provide supplemental UI context for the proof.
  • Reviewed the component harness TSX capture to corroborate the UI behavior demonstrated by the test results.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
README.md Adds a short note pointing users to update instructions when the footer reports a newer release.
docs/quickstart.md Documents OpenCode plugin cache behavior and the supported manual update paths.
src/board.tsx Renders the update availability signal in the footer without changing board behavior.
src/store.tsx Adds a simple store signal for the latest available version.
src/tui.tsx Starts the injected update check from the TUI entrypoint and records newer versions in the store.
src/update-check.ts Introduces version parsing, TTL-backed npm dist-tag lookup, cached fallback handling, and update notification logic.
test/board.test.tsx Covers the new footer indicator rendering when the update signal is set.
test/update-check.test.ts Covers version parsing/comparison, TTL cache behavior, fetch failures, malformed responses, and dev-version suppression.

Reviews (1): Last reviewed commit: "feat: flag when a newer Kagan release is..." | Re-trigger Greptile

OpenCode installs a plugin once and caches it forever — it never re-checks
npm, so users are never told a newer Kagan exists. Check the npm dist-tags
endpoint at most once a day (cached in api.kv across restarts), and show
`→ vX.Y.Z available` in the board footer when a newer release is out.

The check runs off the render path from the TUI entry, skips dev/prerelease
builds so local installs never nag, and never crashes or hangs the board on a
network failure. Docs cover the two real ways to update, since re-running the
install command reuses the same cache and does nothing.
@aorumbayev
aorumbayev merged commit a9a0ae2 into main Jul 9, 2026
3 checks passed
@aorumbayev
aorumbayev deleted the update-banner branch July 9, 2026 01:07
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 0.2.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant