recappi 0.1.28 → 0.1.30

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
@@ -611,7 +611,7 @@ function AccountView({ status }) {
611
611
  function AccountBody({ status }) {
612
612
  return /* @__PURE__ */ jsxs2(Fragment, { children: [
613
613
  /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
614
- /* @__PURE__ */ jsx4(Text2, { bold: true, color: "magenta", children: status.email ?? status.userId ?? "Signed in" }),
614
+ /* @__PURE__ */ jsx4(Text2, { bold: true, color: "green", children: status.email ?? status.userId ?? "Signed in" }),
615
615
  status.email && status.userId ? /* @__PURE__ */ jsx4(Text2, { dimColor: true, children: status.userId }) : null,
616
616
  /* @__PURE__ */ jsx4(Text2, { dimColor: true, children: `origin ${status.origin}` })
617
617
  ] }),
@@ -677,9 +677,9 @@ import { Box as Box3, Text as Text3 } from "ink";
677
677
  import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
678
678
  function Header({ active }) {
679
679
  return /* @__PURE__ */ jsxs3(Box3, { children: [
680
- /* @__PURE__ */ jsxs3(Text3, { bold: true, color: "magenta", children: [
681
- "Recappi",
682
- " "
680
+ /* @__PURE__ */ jsxs3(Text3, { bold: true, color: "green", children: [
681
+ "\u25CF Recappi",
682
+ " "
683
683
  ] }),
684
684
  /* @__PURE__ */ jsx5(Tab, { num: "1", label: "Overview", active: active === "overview" }),
685
685
  /* @__PURE__ */ jsx5(Tab, { num: "2", label: "Jobs", active: active === "jobs" }),
@@ -691,14 +691,27 @@ function Tab({
691
691
  label,
692
692
  active
693
693
  }) {
694
- const text = ` ${num} ${label} `;
695
694
  if (active) {
696
- return /* @__PURE__ */ jsx5(Text3, { bold: true, inverse: true, color: "cyan", children: text });
695
+ return /* @__PURE__ */ jsx5(Text3, { bold: true, inverse: true, color: "cyan", children: ` ${num} ${label} ` });
697
696
  }
698
- return /* @__PURE__ */ jsx5(Text3, { children: text });
697
+ return /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
698
+ " ",
699
+ /* @__PURE__ */ jsx5(Text3, { color: "cyan", children: num }),
700
+ ` ${label} `
701
+ ] });
699
702
  }
700
703
  function Footer({ keys }) {
701
- return /* @__PURE__ */ jsx5(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text3, { dimColor: true, children: keys }) });
704
+ const segments = keys.split(" \xB7 ");
705
+ return /* @__PURE__ */ jsx5(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text3, { children: segments.map((segment, i) => {
706
+ const space = segment.indexOf(" ");
707
+ const key = space === -1 ? segment : segment.slice(0, space);
708
+ const desc = space === -1 ? "" : segment.slice(space);
709
+ return /* @__PURE__ */ jsxs3(Text3, { children: [
710
+ i > 0 ? /* @__PURE__ */ jsx5(Text3, { dimColor: true, children: " \xB7 " }) : null,
711
+ /* @__PURE__ */ jsx5(Text3, { color: "cyan", children: key }),
712
+ /* @__PURE__ */ jsx5(Text3, { dimColor: true, children: desc })
713
+ ] }, `${segment}-${i}`);
714
+ }) }) });
702
715
  }
703
716
  var init_chrome = __esm({
704
717
  "src/tui/chrome.tsx"() {
@@ -898,7 +911,7 @@ function PeekBody({
898
911
  item.contentType || null
899
912
  ].filter(Boolean).join(" \xB7 ");
900
913
  return /* @__PURE__ */ jsxs7(Fragment2, { children: [
901
- /* @__PURE__ */ jsx10(Text8, { bold: true, color: "magenta", wrap: "truncate-end", children: recordingTitle2(item) }),
914
+ /* @__PURE__ */ jsx10(Text8, { bold: true, color: "green", wrap: "truncate-end", children: recordingTitle2(item) }),
902
915
  /* @__PURE__ */ jsx10(Text8, { color: style.color, children: `${style.glyph} ${style.label}` }),
903
916
  meta3 ? /* @__PURE__ */ jsx10(Text8, { dimColor: true, children: meta3 }) : null,
904
917
  /* @__PURE__ */ jsx10(Text8, { dimColor: true, children: formatAge(item.createdAt, nowMs) }),
@@ -1195,7 +1208,7 @@ function RecordingDetailView({
1195
1208
  });
1196
1209
  return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", paddingX: 1, children: [
1197
1210
  /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "\u2039 Recordings" }),
1198
- /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text11, { bold: true, color: "magenta", children: title }) }),
1211
+ /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text11, { bold: true, color: "green", children: title }) }),
1199
1212
  /* @__PURE__ */ jsxs10(Text11, { children: [
1200
1213
  /* @__PURE__ */ jsx13(Text11, { color: style.color, children: `${style.glyph} ${style.label}` }),
1201
1214
  /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: ` ${formatAge(item.createdAt, nowMs) || "\u2014"}` })
@@ -1368,7 +1381,7 @@ function TranscriptView({ loading, data, error: error51 }) {
1368
1381
  const more = win.maxScroll > 0;
1369
1382
  const position = total === 0 ? "" : `${win.start + 1}\u2013${win.end} / ${total}`;
1370
1383
  return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", paddingX: 1, children: [
1371
- /* @__PURE__ */ jsxs11(Text12, { bold: true, color: "magenta", children: [
1384
+ /* @__PURE__ */ jsxs11(Text12, { bold: true, color: "green", children: [
1372
1385
  title,
1373
1386
  more ? /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: ` ${position}` }) : null
1374
1387
  ] }),
@@ -1417,21 +1430,41 @@ function PermissionPreflightView({
1417
1430
  const allGranted = items.length > 0 && items.every((item) => item.status === "granted" && !item.requiresProcessRestart);
1418
1431
  const hasRestartRequired = items.some((item) => item.requiresProcessRestart);
1419
1432
  return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", paddingX: 1, children: [
1420
- /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "\u2039 Recording permissions" }),
1433
+ /* @__PURE__ */ jsxs12(Text13, { children: [
1434
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "\u2039 " }),
1435
+ /* @__PURE__ */ jsx15(Text13, { bold: true, color: "cyan", children: "Recording permissions" })
1436
+ ] }),
1421
1437
  /* @__PURE__ */ jsx15(Box13, { marginTop: 1, flexDirection: "column", children: items.length === 0 ? /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "Checking permissions\u2026" }) : items.map((item) => {
1422
1438
  const status = statusGlyph2(item.status);
1423
- const hint = item.requiresProcessRestart ? item.hint ?? `${item.name} enabled. Run recappi record again to start.` : item.status === "granted" ? void 0 : item.hint ?? DEFAULT_HINTS[item.name];
1439
+ const restart = item.requiresProcessRestart === true;
1440
+ const color = restart ? "yellow" : status.color;
1441
+ const hint = restart ? item.hint ?? `${item.name} enabled. Run recappi record again to start.` : item.status === "granted" ? void 0 : item.hint ?? DEFAULT_HINTS[item.name];
1424
1442
  return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", children: [
1425
1443
  /* @__PURE__ */ jsxs12(Text13, { children: [
1426
- /* @__PURE__ */ jsx15(Text13, { color: status.color, children: status.glyph }),
1444
+ /* @__PURE__ */ jsx15(Text13, { bold: true, color, children: status.glyph }),
1427
1445
  /* @__PURE__ */ jsx15(Text13, { bold: true, children: ` ${item.name}` }),
1428
- /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: ` ${status.label}` })
1446
+ /* @__PURE__ */ jsx15(Text13, { color, children: ` ${status.label}` })
1429
1447
  ] }),
1430
1448
  hint ? /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: ` ${hint}` }) : null
1431
1449
  ] }, item.name);
1432
1450
  }) }),
1433
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: allGranted ? /* @__PURE__ */ jsx15(Text13, { color: "green", children: "All set \u2014 ready to record." }) : hasRestartRequired ? /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "Run recappi record again to start, or press r to retry." }) : /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "Grant the permissions above, then press r to recheck." }) }),
1434
- /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "r recheck \xB7 o open System Settings \xB7 esc back" }) })
1451
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: allGranted ? /* @__PURE__ */ jsx15(Text13, { bold: true, color: "green", children: "\u2713 All set \u2014 ready to record." }) : hasRestartRequired ? /* @__PURE__ */ jsxs12(Text13, { children: [
1452
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "Run recappi record again to start, or press " }),
1453
+ /* @__PURE__ */ jsx15(Text13, { bold: true, color: "cyan", children: "r" }),
1454
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: " to retry." })
1455
+ ] }) : /* @__PURE__ */ jsxs12(Text13, { children: [
1456
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "Grant the permissions above, then press " }),
1457
+ /* @__PURE__ */ jsx15(Text13, { bold: true, color: "cyan", children: "r" }),
1458
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: " to recheck." })
1459
+ ] }) }),
1460
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsxs12(Text13, { children: [
1461
+ /* @__PURE__ */ jsx15(Text13, { color: "cyan", children: "r" }),
1462
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: " recheck \xB7 " }),
1463
+ /* @__PURE__ */ jsx15(Text13, { color: "cyan", children: "o" }),
1464
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: " open System Settings \xB7 " }),
1465
+ /* @__PURE__ */ jsx15(Text13, { color: "cyan", children: "esc" }),
1466
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: " back" })
1467
+ ] }) })
1435
1468
  ] });
1436
1469
  }
1437
1470
  var DEFAULT_HINTS;
@@ -1510,7 +1543,7 @@ function RecordSetupView({
1510
1543
  "esc cancel"
1511
1544
  ].filter(Boolean).join(" \xB7 ");
1512
1545
  return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", paddingX: 1, children: [
1513
- /* @__PURE__ */ jsx16(Text14, { bold: true, color: "magenta", children: "New recording" }),
1546
+ /* @__PURE__ */ jsx16(Text14, { bold: true, color: "green", children: "New recording" }),
1514
1547
  /* @__PURE__ */ jsxs13(Box14, { marginTop: 1, flexDirection: wide ? "row" : "column", children: [
1515
1548
  /* @__PURE__ */ jsx16(Box14, { flexGrow: 1, flexDirection: "column", children: sourceList }),
1516
1549
  /* @__PURE__ */ jsx16(Box14, { marginLeft: wide ? 4 : 0, marginTop: wide ? 0 : 1, children: capturePlan })
@@ -1609,7 +1642,7 @@ function RecordingHeroScreen({
1609
1642
  const badge = paused ? "\u23F8 PAUSED" : starting ? "\u2026" : "\u23FA REC";
1610
1643
  return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", paddingX: 1, height: size.rows, children: [
1611
1644
  /* @__PURE__ */ jsxs14(Text15, { children: [
1612
- /* @__PURE__ */ jsx17(Text15, { bold: true, color: "magenta", children: "recappi" }),
1645
+ /* @__PURE__ */ jsx17(Text15, { bold: true, color: "green", children: "recappi" }),
1613
1646
  /* @__PURE__ */ jsx17(Text15, { dimColor: true, children: " \xB7 Recording" })
1614
1647
  ] }),
1615
1648
  /* @__PURE__ */ jsxs14(Box15, { flexGrow: 1, flexDirection: "column", justifyContent: "center", alignItems: "center", children: [
@@ -20058,8 +20091,19 @@ function readCliVersion() {
20058
20091
  var CLI_VERSION = readCliVersion();
20059
20092
 
20060
20093
  // src/record.tsx
20061
- import { chmodSync, existsSync, statSync } from "fs";
20094
+ import {
20095
+ chmodSync,
20096
+ cpSync,
20097
+ existsSync,
20098
+ mkdirSync as mkdirSync2,
20099
+ readFileSync as readFileSync2,
20100
+ renameSync,
20101
+ rmSync as rmSync2,
20102
+ statSync,
20103
+ writeFileSync
20104
+ } from "fs";
20062
20105
  import { createRequire as createRequire2 } from "module";
20106
+ import { homedir } from "os";
20063
20107
  import { dirname, join as join2 } from "path";
20064
20108
  import { fileURLToPath } from "url";
20065
20109
  import { render, useInput as useInput2 } from "ink";
@@ -20635,7 +20679,7 @@ function resolveSidecarCommand(opts) {
20635
20679
  const command = opts.sidecarCommand?.trim() || opts.env?.[SIDECAR_COMMAND_ENV]?.trim();
20636
20680
  if (command) return command;
20637
20681
  const bundled = bundledSidecarCommand(process.platform, process.arch);
20638
- if (bundled && existsSync(bundled)) return ensureBundledHelperExecutable(bundled);
20682
+ if (bundled && existsSync(bundled)) return ensureBundledHelperExecutable(bundled, opts);
20639
20683
  const platform = `${process.platform}-${process.arch}`;
20640
20684
  if (bundled) {
20641
20685
  throw cliError("record.helper_unavailable", "Recappi recording helper is not available.", {
@@ -20646,16 +20690,17 @@ function resolveSidecarCommand(opts) {
20646
20690
  hint: `No bundled helper is registered for ${platform}. Set ${SIDECAR_COMMAND_ENV} to a compatible helper when one is available.`
20647
20691
  });
20648
20692
  }
20649
- function ensureBundledHelperExecutable(path6) {
20693
+ function ensureBundledHelperExecutable(path6, opts = {}) {
20650
20694
  if (process.platform === "darwin" && path6.endsWith(".app")) {
20651
- const executable = darwinAppExecutablePath(path6);
20695
+ const stableApp = ensureStableDarwinHelperApp(path6, opts);
20696
+ const executable = darwinAppExecutablePath(stableApp);
20652
20697
  if (!existsSync(executable)) {
20653
20698
  throw cliError("record.helper_unavailable", "Recappi recording helper is not available.", {
20654
- hint: `Expected bundled helper executable inside ${path6}. Reinstall recappi, or set ${SIDECAR_COMMAND_ENV} to a compatible helper.`
20699
+ hint: `Expected bundled helper executable inside ${stableApp}. Reinstall recappi, or set ${SIDECAR_COMMAND_ENV} to a compatible helper.`
20655
20700
  });
20656
20701
  }
20657
20702
  ensureExecutableMode(executable);
20658
- return path6;
20703
+ return stableApp;
20659
20704
  }
20660
20705
  if (process.platform === "win32") return path6;
20661
20706
  ensureExecutableMode(path6);
@@ -20673,6 +20718,54 @@ function ensureExecutableMode(path6) {
20673
20718
  });
20674
20719
  }
20675
20720
  }
20721
+ function ensureStableDarwinHelperApp(sourceApp, opts = {}) {
20722
+ const targetApp = stableDarwinHelperAppPath(opts);
20723
+ const markerPath = join2(dirname(targetApp), ".recappi-helper-source");
20724
+ const signature = helperSourceSignature(sourceApp);
20725
+ const currentSignature = readTextIfExists(markerPath);
20726
+ if (existsSync(darwinAppExecutablePath(targetApp)) && currentSignature === signature) {
20727
+ return targetApp;
20728
+ }
20729
+ const tempApp = `${targetApp}.tmp-${process.pid}-${Date.now()}`;
20730
+ try {
20731
+ mkdirSync2(dirname(targetApp), { recursive: true });
20732
+ rmSync2(tempApp, { recursive: true, force: true });
20733
+ cpSync(sourceApp, tempApp, { recursive: true });
20734
+ ensureExecutableMode(darwinAppExecutablePath(tempApp));
20735
+ rmSync2(targetApp, { recursive: true, force: true });
20736
+ renameSync(tempApp, targetApp);
20737
+ writeFileSync(markerPath, signature);
20738
+ return targetApp;
20739
+ } catch (error51) {
20740
+ rmSync2(tempApp, { recursive: true, force: true });
20741
+ const message = error51 instanceof Error ? error51.message : String(error51);
20742
+ throw cliError("record.helper_unavailable", "Recappi recording helper could not be installed.", {
20743
+ hint: `Could not prepare the local recorder at ${targetApp}: ${message}. Reinstall recappi, or set ${SIDECAR_COMMAND_ENV} to a compatible helper.`
20744
+ });
20745
+ }
20746
+ }
20747
+ function stableDarwinHelperAppPath(opts = {}) {
20748
+ const base = opts.env?.RECAPPI_HELPER_HOME?.trim() || join2(opts.homeDir ?? homedir(), "Library", "Application Support", "Recappi", "CLI Helper");
20749
+ return join2(base, `${process.platform}-${process.arch}`, SIDECAR_APP_BUNDLE_NAME);
20750
+ }
20751
+ function helperSourceSignature(sourceApp) {
20752
+ const executable = statSync(darwinAppExecutablePath(sourceApp));
20753
+ const info = statSync(join2(sourceApp, "Contents", "Info.plist"));
20754
+ return JSON.stringify({
20755
+ app: SIDECAR_APP_BUNDLE_NAME,
20756
+ executableSize: executable.size,
20757
+ executableMtimeMs: executable.mtimeMs,
20758
+ infoSize: info.size,
20759
+ infoMtimeMs: info.mtimeMs
20760
+ });
20761
+ }
20762
+ function readTextIfExists(path6) {
20763
+ try {
20764
+ return readFileSync2(path6, "utf8");
20765
+ } catch {
20766
+ return null;
20767
+ }
20768
+ }
20676
20769
  function bundledSidecarCommand(platform, arch) {
20677
20770
  const executable = helperExecutableName(platform);
20678
20771
  if (!executable) return null;