@bubblebrain-ai/bubble 0.0.22 → 0.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,7 +16,9 @@ import { getBubbleHome } from "../bubble-home.js";
16
16
  const require = createRequire(import.meta.url);
17
17
  export const PACKAGE_NAME = "@bubblebrain-ai/bubble";
18
18
  const REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
19
- const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // once a day
19
+ // Throttle for the startup registry check. Short on purpose: with frequent
20
+ // releases, a long TTL means users only learn about a new version a day late.
21
+ const REFRESH_THROTTLE_MS = 30 * 60 * 1000;
20
22
  export function getCurrentVersion() {
21
23
  try {
22
24
  const pkg = require("../../package.json");
@@ -209,32 +211,52 @@ async function writeCache(cache) {
209
211
  // best-effort; never fail startup over a cache write
210
212
  }
211
213
  }
212
- async function refreshCacheInBackground(now) {
213
- const latest = await fetchLatestVersion(4000);
214
- if (latest) {
215
- await writeCache({ lastCheck: now, latest });
216
- }
214
+ function formatUpdateNotice(current, latest) {
215
+ return `Update available: v${current} → v${latest} · run \`bubble update\``;
217
216
  }
218
217
  /**
219
- * Returns a one-line "update available" notice if the cached latest version is
220
- * newer than the running one. Reads only a local cache file (fast, no network
221
- * on the hot path); a stale cache triggers a fire-and-forget refresh so the
222
- * next launch is accurate. Never throws.
218
+ * Startup "update available" check. The immediate `notice` comes from the
219
+ * local cache file (fast, no network on the hot path). A registry refresh
220
+ * always runs in the background (throttled to once per 30 minutes) so a
221
+ * release published since the last launch surfaces in the *current* session
222
+ * via `refreshed`, instead of only after the cache TTL plus another restart.
223
+ * Never throws.
223
224
  */
224
- export async function getStartupUpdateNotice() {
225
+ export async function startStartupUpdateCheck() {
225
226
  try {
226
227
  const current = getCurrentVersion();
227
228
  const now = Date.now();
228
229
  const cache = await readCache();
229
- if (!cache || now - cache.lastCheck > CHECK_INTERVAL_MS) {
230
- void refreshCacheInBackground(now);
231
- }
232
- if (cache && compareVersions(cache.latest, current) > 0) {
233
- return `Update available: v${current} → v${cache.latest} · run \`bubble update\``;
234
- }
235
- return null;
230
+ const notice = cache && compareVersions(cache.latest, current) > 0
231
+ ? formatUpdateNotice(current, cache.latest)
232
+ : null;
233
+ const refreshed = (async () => {
234
+ try {
235
+ if (cache && now - cache.lastCheck < REFRESH_THROTTLE_MS)
236
+ return null;
237
+ const latest = await fetchLatestVersion(4000);
238
+ if (!latest)
239
+ return null;
240
+ await writeCache({ lastCheck: now, latest });
241
+ if (compareVersions(latest, current) <= 0)
242
+ return null;
243
+ // The cache already surfaced this version in `notice` — stay quiet.
244
+ if (notice && cache && compareVersions(latest, cache.latest) <= 0)
245
+ return null;
246
+ return formatUpdateNotice(current, latest);
247
+ }
248
+ catch {
249
+ return null;
250
+ }
251
+ })();
252
+ return { notice, refreshed };
236
253
  }
237
254
  catch {
238
- return null;
255
+ return { notice: null, refreshed: Promise.resolve(null) };
239
256
  }
240
257
  }
258
+ /** Cache-only variant of {@link startStartupUpdateCheck} (still refreshes in the background). */
259
+ export async function getStartupUpdateNotice() {
260
+ const check = await startStartupUpdateCheck();
261
+ return check.notice;
262
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bubblebrain-ai/bubble",
3
- "version": "0.0.22",
3
+ "version": "0.0.24",
4
4
  "description": "A terminal coding agent",
5
5
  "type": "module",
6
6
  "engines": {