recappi 0.1.36 → 0.1.37

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
@@ -597,7 +597,7 @@ var init_LiveCaptionsScreen = __esm({
597
597
  // src/tui/RecordingHeroScreen.tsx
598
598
  import { useEffect as useEffect2, useState as useState3 } from "react";
599
599
  import { Box as Box2, Text as Text2 } from "ink";
600
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
600
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
601
601
  function waveform(samples, width) {
602
602
  if (width <= 0) return "";
603
603
  const tail = samples.slice(-width);
@@ -611,6 +611,7 @@ function waveform(samples, width) {
611
611
  function RecordingHeroScreen({
612
612
  telemetry,
613
613
  artifact,
614
+ captions,
614
615
  canTranscribe = false,
615
616
  canPause = false,
616
617
  now = () => Date.now()
@@ -674,7 +675,8 @@ function RecordingHeroScreen({
674
675
  /* @__PURE__ */ jsx3(Box2, { marginTop: 1, children: /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
675
676
  telemetry.sourceLabel,
676
677
  telemetry.micEnabled ? " + Microphone" : ""
677
- ] }) })
678
+ ] }) }),
679
+ captions ? /* @__PURE__ */ jsx3(Box2, { marginTop: 1, flexDirection: "column", alignItems: "center", width: innerWidth, children: /* @__PURE__ */ jsx3(HeroCaptions, { state: captions }) }) : null
678
680
  ] }),
679
681
  /* @__PURE__ */ jsx3(Box2, { children: /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
680
682
  "q stop & save",
@@ -682,6 +684,25 @@ function RecordingHeroScreen({
682
684
  ] }) })
683
685
  ] });
684
686
  }
687
+ function HeroCaptions({ state }) {
688
+ const MAX_LINES = 3;
689
+ const recent = state.lines.slice(-MAX_LINES);
690
+ const hasPartial = Boolean(state.partial && state.partial.length > 0);
691
+ if (recent.length === 0 && !hasPartial) {
692
+ return /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: state.status === "live" ? "Listening for speech\u2026" : liveCaptionStatusLabel(state.status) });
693
+ }
694
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
695
+ recent.map((line) => /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", alignItems: "center", children: [
696
+ /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate-end", children: [
697
+ line.speaker ? `${line.speaker}: ` : "",
698
+ line.text
699
+ ] }),
700
+ line.translation ? /* @__PURE__ */ jsx3(Text2, { dimColor: true, wrap: "truncate-end", children: `\u21B3 ${line.translation}` }) : null
701
+ ] }, line.id)),
702
+ hasPartial ? /* @__PURE__ */ jsx3(Text2, { dimColor: true, wrap: "truncate-end", children: state.partial }) : null,
703
+ state.translationPartial ? /* @__PURE__ */ jsx3(Text2, { dimColor: true, wrap: "truncate-end", children: `\u21B3 ${state.translationPartial}` }) : null
704
+ ] });
705
+ }
685
706
  function stoppedHandoffCopy(artifact, canTranscribe) {
686
707
  if (artifact?.uploadStatus === "uploading") {
687
708
  return { text: "Uploading\u2026", tone: "normal" };
@@ -708,6 +729,7 @@ var init_RecordingHeroScreen = __esm({
708
729
  "src/tui/RecordingHeroScreen.tsx"() {
709
730
  "use strict";
710
731
  init_format();
732
+ init_liveCaptions();
711
733
  init_terminal();
712
734
  BLOCKS = " \u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588";
713
735
  }
@@ -715,7 +737,7 @@ var init_RecordingHeroScreen = __esm({
715
737
 
716
738
  // src/tui/AccountView.tsx
717
739
  import { Box as Box3, Text as Text3 } from "ink";
718
- import { Fragment, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
740
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
719
741
  function AccountView({ status }) {
720
742
  return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingX: 1, children: [
721
743
  /* @__PURE__ */ jsx5(Text3, { dimColor: true, children: "\u2039 Account" }),
@@ -728,7 +750,7 @@ function AccountView({ status }) {
728
750
  ] });
729
751
  }
730
752
  function AccountBody({ status }) {
731
- return /* @__PURE__ */ jsxs3(Fragment, { children: [
753
+ return /* @__PURE__ */ jsxs3(Fragment2, { children: [
732
754
  /* @__PURE__ */ jsxs3(Box3, { marginTop: 1, flexDirection: "column", children: [
733
755
  /* @__PURE__ */ jsx5(Text3, { bold: true, color: "green", children: status.email ?? status.userId ?? "Signed in" }),
734
756
  status.email && status.userId ? /* @__PURE__ */ jsx5(Text3, { dimColor: true, children: status.userId }) : null,
@@ -1009,7 +1031,7 @@ var init_RecordingsView = __esm({
1009
1031
 
1010
1032
  // src/tui/RecordingPeek.tsx
1011
1033
  import { Box as Box9, Text as Text9 } from "ink";
1012
- import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
1034
+ import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
1013
1035
  function RecordingPeek({
1014
1036
  item,
1015
1037
  summary,
@@ -1029,7 +1051,7 @@ function PeekBody({
1029
1051
  formatBytes2(item.sizeBytes) || null,
1030
1052
  item.contentType || null
1031
1053
  ].filter(Boolean).join(" \xB7 ");
1032
- return /* @__PURE__ */ jsxs8(Fragment2, { children: [
1054
+ return /* @__PURE__ */ jsxs8(Fragment3, { children: [
1033
1055
  /* @__PURE__ */ jsx11(Text9, { bold: true, color: "green", wrap: "truncate-end", children: recordingTitle2(item) }),
1034
1056
  /* @__PURE__ */ jsx11(Text9, { color: style.color, children: `${style.glyph} ${style.label}` }),
1035
1057
  meta3 ? /* @__PURE__ */ jsx11(Text9, { dimColor: true, children: meta3 }) : null,
@@ -1049,7 +1071,7 @@ function SummarySection({
1049
1071
  return /* @__PURE__ */ jsx11(Text9, { dimColor: true, children: `Summary ${summary.status}` });
1050
1072
  }
1051
1073
  const points = (summary.keyPoints ?? []).slice(0, 3);
1052
- return /* @__PURE__ */ jsxs8(Fragment2, { children: [
1074
+ return /* @__PURE__ */ jsxs8(Fragment3, { children: [
1053
1075
  /* @__PURE__ */ jsx11(Text9, { bold: true, children: "Summary" }),
1054
1076
  /* @__PURE__ */ jsx11(Text9, { children: summary.tldr }),
1055
1077
  points.length > 0 ? /* @__PURE__ */ jsx11(Box9, { marginTop: 1, flexDirection: "column", children: points.map((point, i) => /* @__PURE__ */ jsx11(Text9, { dimColor: true, wrap: "truncate-end", children: `\u2022 ${point}` }, i)) }) : null
@@ -1262,7 +1284,7 @@ var init_JobDetailView = __esm({
1262
1284
  // src/tui/RecordingDetailView.tsx
1263
1285
  import React6, { useMemo as useMemo2, useState as useState4 } from "react";
1264
1286
  import { Box as Box12, Text as Text12, useInput as useInput3 } from "ink";
1265
- import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
1287
+ import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
1266
1288
  function RecordingDetailView({
1267
1289
  item,
1268
1290
  nowMs,
@@ -1334,7 +1356,7 @@ function RecordingDetailView({
1334
1356
  ] }),
1335
1357
  meta3 ? /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: meta3 }) : null,
1336
1358
  /* @__PURE__ */ jsx14(AudioActionRow, { item, audio }),
1337
- !item.activeTranscriptId ? /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "Transcript not available yet" }) }) : transcript === "loading" || transcript === void 0 ? /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "Loading\u2026" }) }) : transcript === "error" ? /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "(transcript unavailable)" }) }) : /* @__PURE__ */ jsxs11(Fragment3, { children: [
1359
+ !item.activeTranscriptId ? /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "Transcript not available yet" }) }) : transcript === "loading" || transcript === void 0 ? /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "Loading\u2026" }) }) : transcript === "error" ? /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "(transcript unavailable)" }) }) : /* @__PURE__ */ jsxs11(Fragment4, { children: [
1338
1360
  /* @__PURE__ */ jsx14(TabBar, { active: tab }),
1339
1361
  /* @__PURE__ */ jsx14(Box12, { marginTop: 1, flexDirection: "column", children: tab === "summary" ? /* @__PURE__ */ jsx14(SummaryPane, { summary, budget: paneBudget }) : tab === "chapters" ? /* @__PURE__ */ jsx14(ChaptersPane, { chapters, win: chapWin, selectedIndex: chapterSel }) : /* @__PURE__ */ jsx14(TranscriptPane, { segments, win: segWin }) })
1340
1362
  ] }),
@@ -1399,7 +1421,7 @@ function SummaryPane({
1399
1421
  return /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: `Summary ${summary?.status ?? "unavailable"}` });
1400
1422
  }
1401
1423
  const points = (summary.keyPoints ?? []).slice(0, Math.max(1, budget - 4));
1402
- return /* @__PURE__ */ jsxs11(Fragment3, { children: [
1424
+ return /* @__PURE__ */ jsxs11(Fragment4, { children: [
1403
1425
  /* @__PURE__ */ jsx14(Text12, { children: summary.tldr }),
1404
1426
  points.length > 0 ? /* @__PURE__ */ jsx14(Box12, { marginTop: 1, flexDirection: "column", children: points.map((point, i) => /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: `\u2022 ${point}` }, i)) }) : null
1405
1427
  ] });
@@ -1410,7 +1432,7 @@ function ChaptersPane({
1410
1432
  selectedIndex
1411
1433
  }) {
1412
1434
  if (chapters.length === 0) return /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "No chapters" });
1413
- return /* @__PURE__ */ jsxs11(Fragment3, { children: [
1435
+ return /* @__PURE__ */ jsxs11(Fragment4, { children: [
1414
1436
  chapters.slice(win.start, win.end).map((chapter, i) => {
1415
1437
  const index = win.start + i;
1416
1438
  const selected = index === selectedIndex;
@@ -1428,7 +1450,7 @@ function TranscriptPane({
1428
1450
  win
1429
1451
  }) {
1430
1452
  if (segments.length === 0) return /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "(no segments)" });
1431
- return /* @__PURE__ */ jsxs11(Fragment3, { children: [
1453
+ return /* @__PURE__ */ jsxs11(Fragment4, { children: [
1432
1454
  segments.slice(win.start, win.end).map((seg, i) => /* @__PURE__ */ jsxs11(Text12, { children: [
1433
1455
  /* @__PURE__ */ jsx14(Text12, { color: "blue", children: `[${formatClockMs(seg.startMs)}] ` }),
1434
1456
  seg.speaker ? /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: `${seg.speaker} ` }) : null,
@@ -1698,7 +1720,7 @@ var init_RecordSetupView = __esm({
1698
1720
  // src/tui/AppShell.tsx
1699
1721
  import { useCallback, useEffect as useEffect3, useState as useState7 } from "react";
1700
1722
  import { Box as Box16, Text as Text16, useApp, useInput as useInput6 } from "ink";
1701
- import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
1723
+ import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
1702
1724
  function recordErrorCopy(code, message) {
1703
1725
  switch (code) {
1704
1726
  case "record.helper_unavailable":
@@ -2328,7 +2350,7 @@ function AppShell({
2328
2350
  return /* @__PURE__ */ jsx18(PermissionPreflightView, { items: permissionItemsFromRecordError(liveRecord.data) });
2329
2351
  }
2330
2352
  const copy = recordErrorCopy(liveRecord.code, liveRecord.message);
2331
- return /* @__PURE__ */ jsxs15(Fragment4, { children: [
2353
+ return /* @__PURE__ */ jsxs15(Fragment5, { children: [
2332
2354
  /* @__PURE__ */ jsx18(Text16, { color: copy.tone, children: copy.title }),
2333
2355
  copy.detail ? /* @__PURE__ */ jsx18(Text16, { dimColor: true, children: copy.detail }) : null
2334
2356
  ] });