recappi 0.1.77 → 0.1.78

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.
package/dist/index.js CHANGED
@@ -1000,7 +1000,7 @@ function OverviewView({
1000
1000
  /* @__PURE__ */ jsx12(Text10, { color: "yellow", children: `${queued} queued` })
1001
1001
  ] }) : null,
1002
1002
  stats?.recordings.totalDurationMs != null ? /* @__PURE__ */ jsx12(Text10, { dimColor: true, children: ` \xB7 ${formatClockMs(stats.recordings.totalDurationMs)} transcribed` }) : null,
1003
- revalidating ? /* @__PURE__ */ jsx12(Text10, { dimColor: true, children: " \xB7 syncing" }) : null
1003
+ revalidating ? /* @__PURE__ */ jsx12(Text10, { dimColor: true, children: ` \xB7 ${"\u280B\u2819\u2839\u2838\u283C\u2834\u2826\u2827\u2807\u280F"[spinnerFrame % 10]} syncing` }) : null
1004
1004
  ] }),
1005
1005
  /* @__PURE__ */ jsxs9(Box10, { flexDirection: "row", alignItems: "flex-start", children: [
1006
1006
  /* @__PURE__ */ jsx12(Box10, { flexGrow: 1, flexDirection: "column", children: /* @__PURE__ */ jsx12(
@@ -2071,6 +2071,12 @@ function AppShell({
2071
2071
  void refreshDownloadedIds();
2072
2072
  }, [refreshDownloadedIds]);
2073
2073
  const screen = stack[stack.length - 1];
2074
+ const recordingsRef = useRef3(recordings);
2075
+ recordingsRef.current = recordings;
2076
+ const selectedRef = useRef3(selected);
2077
+ selectedRef.current = selected;
2078
+ const screenRef = useRef3(screen);
2079
+ screenRef.current = screen;
2074
2080
  useEffect4(() => {
2075
2081
  if (screen.kind !== "recordSetup" || !startRecordSetupPreview) return;
2076
2082
  let cancelled = false;
@@ -2278,9 +2284,15 @@ function AppShell({
2278
2284
  setLoadError(jobsR.reason instanceof Error ? jobsR.reason.message : String(jobsR.reason));
2279
2285
  }
2280
2286
  if (recR.status === "fulfilled" && recR.value) {
2281
- setRecordings(recR.value.items);
2287
+ const prevSelectedId = screenRef.current.kind === "overview" ? recordingsRef.current[selectedRef.current]?.recordingId : void 0;
2288
+ const freshItems = recR.value.items;
2289
+ setRecordings(freshItems);
2282
2290
  setRecordingsNextCursor(recR.value.nextCursor ?? null);
2283
2291
  setRecordingsTotalCount(recR.value.totalCount);
2292
+ if (prevSelectedId) {
2293
+ const idx = freshItems.findIndex((r) => r.recordingId === prevSelectedId);
2294
+ setSelected((s) => idx >= 0 ? idx : Math.min(s, Math.max(0, freshItems.length - 1)));
2295
+ }
2284
2296
  }
2285
2297
  if (statsR.status === "fulfilled" && statsR.value) setStats(statsR.value);
2286
2298
  if (accountR.status === "fulfilled") {
@@ -18925,6 +18937,30 @@ function requireAccountPartition(input) {
18925
18937
  function openCliStore(opts = {}) {
18926
18938
  return new CliLocalStore(opts);
18927
18939
  }
18940
+ function isLocalStoreUnavailableError(error51) {
18941
+ return typeof error51 === "object" && error51 !== null && error51.localStoreUnavailable === true;
18942
+ }
18943
+ var warnedLocalStoreUnavailable = false;
18944
+ function tryOpenCliStore(opts = {}) {
18945
+ const { onUnavailable, open = openCliStore, ...storeOpts } = opts;
18946
+ try {
18947
+ return open(storeOpts);
18948
+ } catch (error51) {
18949
+ if (isLocalStoreUnavailableError(error51)) {
18950
+ if (!warnedLocalStoreUnavailable) {
18951
+ warnedLocalStoreUnavailable = true;
18952
+ (onUnavailable ?? defaultWarnLocalStoreUnavailable)();
18953
+ }
18954
+ return null;
18955
+ }
18956
+ throw error51;
18957
+ }
18958
+ }
18959
+ function defaultWarnLocalStoreUnavailable() {
18960
+ process.stderr.write(
18961
+ "Local cache unavailable (needs Node.js 22+ for node:sqlite). Cloud commands work normally.\n"
18962
+ );
18963
+ }
18928
18964
  var CliLocalStore = class {
18929
18965
  db;
18930
18966
  now;
@@ -19220,9 +19256,11 @@ function suppressNodeSqliteWarning(run) {
19220
19256
  return run();
19221
19257
  } catch (error51) {
19222
19258
  if (isMissingNodeSqlite(error51)) {
19223
- throw cliError("internal.unexpected", "Local SQLite store requires Node.js 22 or newer.", {
19259
+ const err = cliError("internal.unexpected", "Local SQLite store requires Node.js 22 or newer.", {
19224
19260
  hint: "Upgrade Node.js, then retry. Cloud-only commands that do not touch local state can still run."
19225
19261
  });
19262
+ err.localStoreUnavailable = true;
19263
+ throw err;
19226
19264
  }
19227
19265
  throw error51;
19228
19266
  } finally {
@@ -19549,21 +19587,23 @@ var RecappiApiClient = class {
19549
19587
  let accountScopedArtifacts = 0;
19550
19588
  let unattributedArtifacts = 0;
19551
19589
  if (status.loggedIn && status.userId) {
19552
- const store = openCliStore({
19590
+ const store = tryOpenCliStore({
19553
19591
  dbPath: storePath,
19554
19592
  env: this.env,
19555
19593
  homeDir: this.homeDir
19556
19594
  });
19557
- try {
19558
- const account = requireAccountPartition({
19559
- backendOrigin: this.auth.origin,
19560
- userId: status.userId
19561
- });
19562
- store.recordAccountSeen(account, status.email);
19563
- accountScopedArtifacts = store.listLocalArtifactsForAccount(account).length;
19564
- unattributedArtifacts = store.listUnattributedLocalArtifacts().length;
19565
- } finally {
19566
- store.close();
19595
+ if (store) {
19596
+ try {
19597
+ const account = requireAccountPartition({
19598
+ backendOrigin: this.auth.origin,
19599
+ userId: status.userId
19600
+ });
19601
+ store.recordAccountSeen(account, status.email);
19602
+ accountScopedArtifacts = store.listLocalArtifactsForAccount(account).length;
19603
+ unattributedArtifacts = store.listUnattributedLocalArtifacts().length;
19604
+ } finally {
19605
+ store.close();
19606
+ }
19567
19607
  }
19568
19608
  }
19569
19609
  const billing = status.loggedIn ? await this.billingStatus() : void 0;
@@ -20292,7 +20332,7 @@ async function findReusableDownload(recordingId, deps) {
20292
20332
  if (!artifact || !await isReadableFile(artifact.localPath)) return null;
20293
20333
  const opened = store.markLocalArtifactOpened(artifact.id);
20294
20334
  return artifactToDownload(opened, recordingId);
20295
- });
20335
+ }, null);
20296
20336
  }
20297
20337
  async function rememberDownload(download, deps) {
20298
20338
  return withStore(deps, (store, account) => {
@@ -20310,12 +20350,13 @@ async function rememberDownload(download, deps) {
20310
20350
  }
20311
20351
  });
20312
20352
  return store.markLocalArtifactOpened(artifact.id);
20313
- });
20353
+ }, null);
20314
20354
  }
20315
20355
  async function listExistingDownloads(deps) {
20316
20356
  const artifacts = await withStore(
20317
20357
  deps,
20318
- (store, account) => account ? store.listLocalArtifactsForAccount(account, { kind: "download" }) : []
20358
+ (store, account) => account ? store.listLocalArtifactsForAccount(account, { kind: "download" }) : [],
20359
+ []
20319
20360
  );
20320
20361
  const existing = [];
20321
20362
  for (const artifact of artifacts) {
@@ -20323,8 +20364,9 @@ async function listExistingDownloads(deps) {
20323
20364
  }
20324
20365
  return existing;
20325
20366
  }
20326
- async function withStore(deps, run) {
20327
- const store = deps.store ?? openCliStore({ homeDir: deps.homeDir, env: deps.env });
20367
+ async function withStore(deps, run, fallback) {
20368
+ const store = deps.store ?? tryOpenCliStore({ homeDir: deps.homeDir, env: deps.env });
20369
+ if (!store) return fallback;
20328
20370
  try {
20329
20371
  return await run(store, deps.account ?? null);
20330
20372
  } finally {
@@ -20657,7 +20699,7 @@ async function findIndexedRecordingSessionDir(recordingId, deps) {
20657
20699
  const manifest = await readJsonRecord(path6.join(artifact.localPath, "remote-session.json"));
20658
20700
  if (manifest?.recordingId && manifest.recordingId !== recordingId) return void 0;
20659
20701
  return artifact.localPath;
20660
- });
20702
+ }, void 0);
20661
20703
  }
20662
20704
  async function rememberRecordingSession(input, deps) {
20663
20705
  return withSessionStore(deps, (store, account) => {
@@ -20680,7 +20722,7 @@ async function rememberRecordingSession(input, deps) {
20680
20722
  indexedAt: (input.now ?? (() => /* @__PURE__ */ new Date()))().toISOString()
20681
20723
  })
20682
20724
  });
20683
- });
20725
+ }, null);
20684
20726
  }
20685
20727
  async function listCachedRecordingSessions(deps) {
20686
20728
  const limit = deps.limit ?? 50;
@@ -20698,7 +20740,7 @@ async function listCachedRecordingSessions(deps) {
20698
20740
  recordings.push(recording);
20699
20741
  }
20700
20742
  return recordings.sort((a, b) => b.createdAt - a.createdAt || b.updatedAt - a.updatedAt);
20701
- });
20743
+ }, []);
20702
20744
  return recordingListDataSchema.parse({
20703
20745
  items,
20704
20746
  limit,
@@ -20715,8 +20757,9 @@ async function recordingFromArtifact(artifact) {
20715
20757
  const parsed = recordingDataSchema.safeParse(fromFile);
20716
20758
  return parsed.success ? parsed.data : null;
20717
20759
  }
20718
- async function withSessionStore(deps, run) {
20719
- const store = deps.store ?? openCliStore({ homeDir: deps.homeDir, env: deps.env });
20760
+ async function withSessionStore(deps, run, fallback) {
20761
+ const store = deps.store ?? tryOpenCliStore({ homeDir: deps.homeDir, env: deps.env });
20762
+ if (!store) return fallback;
20720
20763
  try {
20721
20764
  return await run(store, deps.account ?? null);
20722
20765
  } finally {