recappi 0.1.11 → 0.1.13
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 +222 -56
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1293,33 +1293,124 @@ var init_TranscriptView = __esm({
|
|
|
1293
1293
|
}
|
|
1294
1294
|
});
|
|
1295
1295
|
|
|
1296
|
+
// src/tui/PermissionPreflightView.tsx
|
|
1297
|
+
import { Box as Box13, Text as Text13 } from "ink";
|
|
1298
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1299
|
+
function statusGlyph2(status) {
|
|
1300
|
+
switch (status) {
|
|
1301
|
+
case "granted":
|
|
1302
|
+
return { glyph: "\u2713", color: "green", label: "granted" };
|
|
1303
|
+
case "denied":
|
|
1304
|
+
return { glyph: "\u2717", color: "red", label: "not allowed" };
|
|
1305
|
+
case "unknown":
|
|
1306
|
+
return { glyph: "\u25CB", color: "yellow", label: "not requested yet" };
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
function PermissionPreflightView({
|
|
1310
|
+
items
|
|
1311
|
+
}) {
|
|
1312
|
+
const allGranted = items.length > 0 && items.every((item) => item.status === "granted");
|
|
1313
|
+
return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", paddingX: 1, children: [
|
|
1314
|
+
/* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "\u2039 Recording permissions" }),
|
|
1315
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, flexDirection: "column", children: items.length === 0 ? /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "Checking permissions\u2026" }) : items.map((item) => {
|
|
1316
|
+
const status = statusGlyph2(item.status);
|
|
1317
|
+
const hint = item.status === "granted" ? void 0 : item.hint ?? DEFAULT_HINTS[item.name];
|
|
1318
|
+
return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", children: [
|
|
1319
|
+
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
1320
|
+
/* @__PURE__ */ jsx15(Text13, { color: status.color, children: status.glyph }),
|
|
1321
|
+
/* @__PURE__ */ jsx15(Text13, { bold: true, children: ` ${item.name}` }),
|
|
1322
|
+
/* @__PURE__ */ jsx15(Text13, { dimColor: true, children: ` ${status.label}` })
|
|
1323
|
+
] }),
|
|
1324
|
+
hint ? /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: ` ${hint}` }) : null
|
|
1325
|
+
] }, item.name);
|
|
1326
|
+
}) }),
|
|
1327
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: allGranted ? /* @__PURE__ */ jsx15(Text13, { color: "green", children: "All set \u2014 ready to record." }) : /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "Grant the permissions above, then press r to recheck." }) }),
|
|
1328
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "r recheck \xB7 o open System Settings \xB7 esc back" }) })
|
|
1329
|
+
] });
|
|
1330
|
+
}
|
|
1331
|
+
var DEFAULT_HINTS;
|
|
1332
|
+
var init_PermissionPreflightView = __esm({
|
|
1333
|
+
"src/tui/PermissionPreflightView.tsx"() {
|
|
1334
|
+
"use strict";
|
|
1335
|
+
DEFAULT_HINTS = {
|
|
1336
|
+
"Screen Recording": "Open System Settings \u203A Privacy & Security \u203A Screen Recording, enable recappi, then recheck.",
|
|
1337
|
+
Microphone: "Open System Settings \u203A Privacy & Security \u203A Microphone, enable recappi, then recheck."
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
});
|
|
1341
|
+
|
|
1296
1342
|
// src/tui/AppShell.tsx
|
|
1297
1343
|
import { useCallback, useEffect as useEffect2, useState as useState5 } from "react";
|
|
1298
|
-
import { Box as
|
|
1299
|
-
import { Fragment as Fragment4, jsx as
|
|
1344
|
+
import { Box as Box14, Text as Text14, useApp, useInput as useInput5 } from "ink";
|
|
1345
|
+
import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1300
1346
|
function recordErrorCopy(code, message) {
|
|
1301
1347
|
switch (code) {
|
|
1302
1348
|
case "record.helper_unavailable":
|
|
1303
1349
|
return {
|
|
1304
|
-
title: "
|
|
1305
|
-
detail: "
|
|
1350
|
+
title: "This CLI install is missing its local recorder.",
|
|
1351
|
+
detail: "Run npm install -g recappi@latest, or use npx -y recappi@latest.",
|
|
1306
1352
|
tone: "yellow"
|
|
1307
1353
|
};
|
|
1308
1354
|
case "record.unsupported_platform":
|
|
1309
1355
|
return {
|
|
1310
|
-
title: "
|
|
1356
|
+
title: "CLI recording isn't supported on this platform yet.",
|
|
1357
|
+
detail: "Use Recappi Mini on macOS to record for now.",
|
|
1311
1358
|
tone: "yellow"
|
|
1312
1359
|
};
|
|
1313
1360
|
case "record.capture_unavailable":
|
|
1314
1361
|
return {
|
|
1315
|
-
title: "
|
|
1316
|
-
detail: "
|
|
1362
|
+
title: "CLI recording isn't ready yet.",
|
|
1363
|
+
detail: "Use the Recappi Mini app to record for now; CLI recording is coming soon.",
|
|
1364
|
+
tone: "yellow"
|
|
1365
|
+
};
|
|
1366
|
+
case "record.permission_required":
|
|
1367
|
+
return {
|
|
1368
|
+
title: "Recording needs macOS permission first.",
|
|
1369
|
+
detail: "Open System Settings > Privacy & Security, allow recording access, then retry.",
|
|
1317
1370
|
tone: "yellow"
|
|
1318
1371
|
};
|
|
1372
|
+
case "record.capture_failed":
|
|
1373
|
+
return {
|
|
1374
|
+
title: "Recording couldn't capture audio.",
|
|
1375
|
+
detail: "Check permissions, make sure audio is playing, then try again.",
|
|
1376
|
+
tone: "red"
|
|
1377
|
+
};
|
|
1319
1378
|
default:
|
|
1320
1379
|
return { title: "Couldn't start recording.", detail: message, tone: "red" };
|
|
1321
1380
|
}
|
|
1322
1381
|
}
|
|
1382
|
+
function recordErrorState(error51) {
|
|
1383
|
+
if (error51 instanceof Error) {
|
|
1384
|
+
const descriptor = isRecord6(error51) && isRecord6(error51.descriptor) ? error51.descriptor : void 0;
|
|
1385
|
+
return {
|
|
1386
|
+
kind: "error",
|
|
1387
|
+
message: error51.message,
|
|
1388
|
+
code: typeof descriptor?.code === "string" ? descriptor.code : "code" in error51 && typeof error51.code === "string" ? error51.code : void 0,
|
|
1389
|
+
data: isRecord6(error51) ? error51.data : void 0
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
return { kind: "error", message: String(error51) };
|
|
1393
|
+
}
|
|
1394
|
+
function permissionItemsFromRecordError(data) {
|
|
1395
|
+
const sidecarError = isRecord6(data) ? data : void 0;
|
|
1396
|
+
const sidecarData = isRecord6(sidecarError?.data) ? sidecarError.data : void 0;
|
|
1397
|
+
const permission = typeof sidecarData?.permission === "string" ? sidecarData.permission : "";
|
|
1398
|
+
const hint = typeof sidecarData?.recovery === "string" ? sidecarData.recovery : void 0;
|
|
1399
|
+
const item = permission === "microphone" ? "Microphone" : permission === "screen_recording" ? "Screen Recording" : "Recording";
|
|
1400
|
+
return [{ name: item, status: "denied", ...hint ? { hint } : {} }];
|
|
1401
|
+
}
|
|
1402
|
+
function settingsUrlFromRecordError(data) {
|
|
1403
|
+
const sidecarError = isRecord6(data) ? data : void 0;
|
|
1404
|
+
const sidecarData = isRecord6(sidecarError?.data) ? sidecarError.data : void 0;
|
|
1405
|
+
const permission = typeof sidecarData?.permission === "string" ? sidecarData.permission : "";
|
|
1406
|
+
if (permission === "microphone") {
|
|
1407
|
+
return "x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone";
|
|
1408
|
+
}
|
|
1409
|
+
return "x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture";
|
|
1410
|
+
}
|
|
1411
|
+
function isRecord6(value) {
|
|
1412
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1413
|
+
}
|
|
1323
1414
|
function AppShell({
|
|
1324
1415
|
fetchJobs,
|
|
1325
1416
|
fetchTranscript,
|
|
@@ -1358,6 +1449,7 @@ function AppShell({
|
|
|
1358
1449
|
const [audioCache, setAudioCache] = useState5(() => /* @__PURE__ */ new Map());
|
|
1359
1450
|
const [downloadedIds, setDownloadedIds] = useState5(() => /* @__PURE__ */ new Set());
|
|
1360
1451
|
const [liveRecord, setLiveRecord] = useState5(void 0);
|
|
1452
|
+
const [recordRetryNonce, setRecordRetryNonce] = useState5(0);
|
|
1361
1453
|
const refreshDownloadedIds = useCallback(async () => {
|
|
1362
1454
|
if (!listDownloadedRecordingIds) return;
|
|
1363
1455
|
try {
|
|
@@ -1402,18 +1494,13 @@ function AppShell({
|
|
|
1402
1494
|
setLiveRecord({ kind: "live", session });
|
|
1403
1495
|
}).catch((error51) => {
|
|
1404
1496
|
if (!cancelled) {
|
|
1405
|
-
|
|
1406
|
-
setLiveRecord({
|
|
1407
|
-
kind: "error",
|
|
1408
|
-
code,
|
|
1409
|
-
message: error51 instanceof Error ? error51.message : String(error51)
|
|
1410
|
-
});
|
|
1497
|
+
setLiveRecord(recordErrorState(error51));
|
|
1411
1498
|
}
|
|
1412
1499
|
});
|
|
1413
1500
|
return () => {
|
|
1414
1501
|
cancelled = true;
|
|
1415
1502
|
};
|
|
1416
|
-
}, [screen.kind, startLiveRecord]);
|
|
1503
|
+
}, [screen.kind, startLiveRecord, recordRetryNonce]);
|
|
1417
1504
|
const selectedRecording = screen.kind === "overview" ? recordings[selected] : void 0;
|
|
1418
1505
|
const peekTranscriptId = selectedRecording?.activeTranscriptId ?? void 0;
|
|
1419
1506
|
useEffect2(() => {
|
|
@@ -1591,6 +1678,14 @@ function AppShell({
|
|
|
1591
1678
|
useInput5((input, key) => {
|
|
1592
1679
|
setNotice(void 0);
|
|
1593
1680
|
if (screen.kind === "record") {
|
|
1681
|
+
if (liveRecord?.kind === "error" && input === "r") {
|
|
1682
|
+
setRecordRetryNonce((value) => value + 1);
|
|
1683
|
+
return;
|
|
1684
|
+
}
|
|
1685
|
+
if (liveRecord?.kind === "error" && input === "o") {
|
|
1686
|
+
openUrl2?.(settingsUrlFromRecordError(liveRecord.data));
|
|
1687
|
+
return;
|
|
1688
|
+
}
|
|
1594
1689
|
if (input === "q" || key.escape || key.leftArrow) void stopLiveRecord();
|
|
1595
1690
|
return;
|
|
1596
1691
|
}
|
|
@@ -1646,18 +1741,18 @@ function AppShell({
|
|
|
1646
1741
|
}
|
|
1647
1742
|
});
|
|
1648
1743
|
if (screen.kind === "transcript") {
|
|
1649
|
-
return /* @__PURE__ */
|
|
1744
|
+
return /* @__PURE__ */ jsx16(TranscriptView, { loading: screen.loading, data: screen.data, error: screen.error });
|
|
1650
1745
|
}
|
|
1651
1746
|
if (screen.kind === "jobDetail") {
|
|
1652
1747
|
const job = jobs.find((j) => j.jobId === screen.jobId);
|
|
1653
|
-
if (!job) return /* @__PURE__ */
|
|
1654
|
-
return /* @__PURE__ */
|
|
1748
|
+
if (!job) return /* @__PURE__ */ jsx16(Missing, { label: "Job" });
|
|
1749
|
+
return /* @__PURE__ */ jsx16(Detail, { notice, children: /* @__PURE__ */ jsx16(JobDetailView, { item: job, origin, spinnerFrame, nowMs: now() }) });
|
|
1655
1750
|
}
|
|
1656
1751
|
if (screen.kind === "recordingDetail") {
|
|
1657
1752
|
const rec = recordings.find((r) => r.recordingId === screen.recordingId);
|
|
1658
|
-
if (!rec) return /* @__PURE__ */
|
|
1753
|
+
if (!rec) return /* @__PURE__ */ jsx16(Missing, { label: "Recording" });
|
|
1659
1754
|
const detailTranscript = rec.activeTranscriptId ? transcriptCache.get(rec.activeTranscriptId) : void 0;
|
|
1660
|
-
return /* @__PURE__ */
|
|
1755
|
+
return /* @__PURE__ */ jsx16(Detail, { notice, children: /* @__PURE__ */ jsx16(
|
|
1661
1756
|
RecordingDetailView,
|
|
1662
1757
|
{
|
|
1663
1758
|
item: rec,
|
|
@@ -1669,18 +1764,21 @@ function AppShell({
|
|
|
1669
1764
|
}
|
|
1670
1765
|
if (screen.kind === "record") {
|
|
1671
1766
|
if (liveRecord?.kind === "live") {
|
|
1672
|
-
return /* @__PURE__ */
|
|
1767
|
+
return /* @__PURE__ */ jsx16(LiveCaptionsScreen, { source: liveRecord.session.source, now });
|
|
1673
1768
|
}
|
|
1674
|
-
return /* @__PURE__ */
|
|
1675
|
-
/* @__PURE__ */
|
|
1676
|
-
/* @__PURE__ */
|
|
1769
|
+
return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", height: size.rows, paddingX: 1, children: [
|
|
1770
|
+
/* @__PURE__ */ jsx16(Header, { active: "record" }),
|
|
1771
|
+
/* @__PURE__ */ jsx16(Box14, { flexGrow: 1, flexDirection: "column", paddingX: 1, paddingTop: 1, children: liveRecord?.kind === "error" ? (() => {
|
|
1772
|
+
if (liveRecord.code === "record.permission_required") {
|
|
1773
|
+
return /* @__PURE__ */ jsx16(PermissionPreflightView, { items: permissionItemsFromRecordError(liveRecord.data) });
|
|
1774
|
+
}
|
|
1677
1775
|
const copy = recordErrorCopy(liveRecord.code, liveRecord.message);
|
|
1678
|
-
return /* @__PURE__ */
|
|
1679
|
-
/* @__PURE__ */
|
|
1680
|
-
copy.detail ? /* @__PURE__ */
|
|
1776
|
+
return /* @__PURE__ */ jsxs13(Fragment4, { children: [
|
|
1777
|
+
/* @__PURE__ */ jsx16(Text14, { color: copy.tone, children: copy.title }),
|
|
1778
|
+
copy.detail ? /* @__PURE__ */ jsx16(Text14, { dimColor: true, children: copy.detail }) : null
|
|
1681
1779
|
] });
|
|
1682
|
-
})() : /* @__PURE__ */
|
|
1683
|
-
/* @__PURE__ */
|
|
1780
|
+
})() : /* @__PURE__ */ jsx16(Text14, { dimColor: true, children: "Starting live recording\u2026" }) }),
|
|
1781
|
+
/* @__PURE__ */ jsx16(Footer, { keys: "q / esc / \u2190 back" })
|
|
1684
1782
|
] });
|
|
1685
1783
|
}
|
|
1686
1784
|
const tab = screen.kind === "jobs" ? "jobs" : screen.kind === "account" ? "account" : "overview";
|
|
@@ -1698,7 +1796,7 @@ function AppShell({
|
|
|
1698
1796
|
const showPeek = size.columns >= 100;
|
|
1699
1797
|
const peekWidth = showPeek ? 34 : 0;
|
|
1700
1798
|
const listColumns = showPeek ? Math.max(30, size.columns - peekWidth - 3) : size.columns;
|
|
1701
|
-
body = /* @__PURE__ */
|
|
1799
|
+
body = /* @__PURE__ */ jsx16(
|
|
1702
1800
|
OverviewView,
|
|
1703
1801
|
{
|
|
1704
1802
|
recordings: recordings.slice(win.start, win.end),
|
|
@@ -1718,11 +1816,11 @@ function AppShell({
|
|
|
1718
1816
|
);
|
|
1719
1817
|
} else if (screen.kind === "account") {
|
|
1720
1818
|
position = "";
|
|
1721
|
-
body = /* @__PURE__ */
|
|
1819
|
+
body = /* @__PURE__ */ jsx16(AccountView, { status: accountStatus });
|
|
1722
1820
|
} else {
|
|
1723
1821
|
const win = listWindow(selected, jobs.length, Math.max(3, size.rows - 4));
|
|
1724
1822
|
position = jobs.length ? `${selected + 1} / ${jobs.length}` : "0";
|
|
1725
|
-
body = /* @__PURE__ */
|
|
1823
|
+
body = /* @__PURE__ */ jsx16(
|
|
1726
1824
|
JobsView,
|
|
1727
1825
|
{
|
|
1728
1826
|
items: jobs.slice(win.start, win.end),
|
|
@@ -1732,34 +1830,34 @@ function AppShell({
|
|
|
1732
1830
|
);
|
|
1733
1831
|
}
|
|
1734
1832
|
const footerKeys = screen.kind === "jobs" ? `${position} \xB7 \u2191\u2193 select \xB7 \u23CE job \xB7 t transcript \xB7 1 overview \xB7 3 account \xB7 4 record \xB7 r refresh \xB7 q quit` : screen.kind === "account" ? "3 account \xB7 1 overview \xB7 2 jobs \xB7 4 record \xB7 r refresh \xB7 q quit" : `${position} \xB7 \u2191\u2193 scroll \xB7 \u23CE open \xB7 t transcript \xB7 2 jobs \xB7 3 account \xB7 4 record \xB7 r refresh \xB7 q quit`;
|
|
1735
|
-
return /* @__PURE__ */
|
|
1736
|
-
/* @__PURE__ */
|
|
1737
|
-
/* @__PURE__ */
|
|
1833
|
+
return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", height: size.rows, paddingX: 1, children: [
|
|
1834
|
+
/* @__PURE__ */ jsx16(Header, { active: tab }),
|
|
1835
|
+
/* @__PURE__ */ jsxs13(Box14, { flexGrow: 1, flexDirection: "column", children: [
|
|
1738
1836
|
body,
|
|
1739
|
-
loadError && jobs.length === 0 && recordings.length === 0 ? /* @__PURE__ */
|
|
1837
|
+
loadError && jobs.length === 0 && recordings.length === 0 ? /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsxs13(Text14, { color: "red", children: [
|
|
1740
1838
|
"! ",
|
|
1741
1839
|
loadError
|
|
1742
1840
|
] }) }) : null
|
|
1743
1841
|
] }),
|
|
1744
|
-
/* @__PURE__ */
|
|
1842
|
+
/* @__PURE__ */ jsx16(Footer, { keys: footerKeys })
|
|
1745
1843
|
] });
|
|
1746
1844
|
}
|
|
1747
1845
|
function Detail({
|
|
1748
1846
|
notice,
|
|
1749
1847
|
children
|
|
1750
1848
|
}) {
|
|
1751
|
-
return /* @__PURE__ */
|
|
1849
|
+
return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", children: [
|
|
1752
1850
|
children,
|
|
1753
|
-
notice ? /* @__PURE__ */
|
|
1851
|
+
notice ? /* @__PURE__ */ jsx16(Box14, { paddingX: 1, children: /* @__PURE__ */ jsx16(Text14, { color: "green", children: notice }) }) : null
|
|
1754
1852
|
] });
|
|
1755
1853
|
}
|
|
1756
1854
|
function Missing({ label }) {
|
|
1757
|
-
return /* @__PURE__ */
|
|
1758
|
-
/* @__PURE__ */
|
|
1855
|
+
return /* @__PURE__ */ jsxs13(Box14, { flexDirection: "column", paddingX: 1, children: [
|
|
1856
|
+
/* @__PURE__ */ jsxs13(Text14, { dimColor: true, children: [
|
|
1759
1857
|
label,
|
|
1760
1858
|
" no longer in the list."
|
|
1761
1859
|
] }),
|
|
1762
|
-
/* @__PURE__ */
|
|
1860
|
+
/* @__PURE__ */ jsx16(Text14, { dimColor: true, children: "esc back \xB7 q quit" })
|
|
1763
1861
|
] });
|
|
1764
1862
|
}
|
|
1765
1863
|
var RECORDINGS_PAGE_SIZE, RECORDINGS_PREFETCH_REMAINING;
|
|
@@ -1774,6 +1872,7 @@ var init_AppShell = __esm({
|
|
|
1774
1872
|
init_RecordingDetailView();
|
|
1775
1873
|
init_TranscriptView();
|
|
1776
1874
|
init_LiveCaptionsScreen();
|
|
1875
|
+
init_PermissionPreflightView();
|
|
1777
1876
|
init_format();
|
|
1778
1877
|
init_terminal();
|
|
1779
1878
|
RECORDINGS_PAGE_SIZE = 50;
|
|
@@ -16399,6 +16498,8 @@ var cliErrorCodeSchema = external_exports.enum([
|
|
|
16399
16498
|
"record.helper_unavailable",
|
|
16400
16499
|
"record.unsupported_platform",
|
|
16401
16500
|
"record.capture_unavailable",
|
|
16501
|
+
"record.permission_required",
|
|
16502
|
+
"record.capture_failed",
|
|
16402
16503
|
"cloud.conflict.upload_in_progress",
|
|
16403
16504
|
"cloud.recording_not_ready",
|
|
16404
16505
|
"cloud.job_failed",
|
|
@@ -16495,6 +16596,19 @@ var sidecarRecordingOptionsSchema = external_exports.object({
|
|
|
16495
16596
|
transcriptionLanguage: external_exports.string().optional(),
|
|
16496
16597
|
title: external_exports.string().optional()
|
|
16497
16598
|
});
|
|
16599
|
+
var sidecarPermissionNameSchema = external_exports.enum(["screen_recording", "microphone"]);
|
|
16600
|
+
var sidecarPermissionStatusSchema = external_exports.enum(["granted", "denied", "unknown"]);
|
|
16601
|
+
var sidecarPermissionItemSchema = external_exports.object({
|
|
16602
|
+
name: sidecarPermissionNameSchema,
|
|
16603
|
+
status: sidecarPermissionStatusSchema,
|
|
16604
|
+
hint: external_exports.string().optional()
|
|
16605
|
+
});
|
|
16606
|
+
var sidecarPermissionStatusParamsSchema = external_exports.object({
|
|
16607
|
+
options: sidecarRecordingOptionsSchema
|
|
16608
|
+
});
|
|
16609
|
+
var sidecarPermissionStatusResultSchema = external_exports.object({
|
|
16610
|
+
permissions: external_exports.array(sidecarPermissionItemSchema)
|
|
16611
|
+
});
|
|
16498
16612
|
var sidecarRecordingStateSchema = external_exports.enum([
|
|
16499
16613
|
"idle",
|
|
16500
16614
|
"starting",
|
|
@@ -16566,6 +16680,12 @@ var sidecarRequestSchema = external_exports.discriminatedUnion("method", [
|
|
|
16566
16680
|
method: external_exports.literal("recappi.recording.start"),
|
|
16567
16681
|
params: sidecarRecordingStartParamsSchema
|
|
16568
16682
|
}),
|
|
16683
|
+
external_exports.object({
|
|
16684
|
+
jsonrpc: external_exports.literal("2.0"),
|
|
16685
|
+
id: sidecarJsonRpcIdSchema,
|
|
16686
|
+
method: external_exports.literal("recappi.permissions.status"),
|
|
16687
|
+
params: sidecarPermissionStatusParamsSchema
|
|
16688
|
+
}),
|
|
16569
16689
|
external_exports.object({
|
|
16570
16690
|
jsonrpc: external_exports.literal("2.0"),
|
|
16571
16691
|
id: sidecarJsonRpcIdSchema,
|
|
@@ -16893,6 +17013,8 @@ var DEFAULT_EXIT_CODES = {
|
|
|
16893
17013
|
"record.helper_unavailable": 2,
|
|
16894
17014
|
"record.unsupported_platform": 2,
|
|
16895
17015
|
"record.capture_unavailable": 2,
|
|
17016
|
+
"record.permission_required": 2,
|
|
17017
|
+
"record.capture_failed": 1,
|
|
16896
17018
|
"cloud.conflict.upload_in_progress": 5,
|
|
16897
17019
|
"cloud.recording_not_ready": 5,
|
|
16898
17020
|
"cloud.job_failed": 5,
|
|
@@ -19419,6 +19541,13 @@ var MiniSidecarClient = class {
|
|
|
19419
19541
|
sidecarRecordingStartResultSchema
|
|
19420
19542
|
);
|
|
19421
19543
|
}
|
|
19544
|
+
getPermissionStatus(params) {
|
|
19545
|
+
return this.request(
|
|
19546
|
+
"recappi.permissions.status",
|
|
19547
|
+
sidecarPermissionStatusParamsSchema.parse(params),
|
|
19548
|
+
sidecarPermissionStatusResultSchema
|
|
19549
|
+
);
|
|
19550
|
+
}
|
|
19422
19551
|
stopRecording(params) {
|
|
19423
19552
|
return this.request(
|
|
19424
19553
|
"recappi.recording.stop",
|
|
@@ -19519,12 +19648,7 @@ var MiniSidecarClient = class {
|
|
|
19519
19648
|
this.pending.delete(id);
|
|
19520
19649
|
clearTimeout(pending.timer);
|
|
19521
19650
|
if ("error" in response.data) {
|
|
19522
|
-
pending.reject(
|
|
19523
|
-
cliError("internal.unexpected", response.data.error.message, {
|
|
19524
|
-
data: response.data.error,
|
|
19525
|
-
retryable: response.data.error.code >= -32099 && response.data.error.code <= -32e3
|
|
19526
|
-
})
|
|
19527
|
-
);
|
|
19651
|
+
pending.reject(sidecarErrorToCliError(response.data.error));
|
|
19528
19652
|
return;
|
|
19529
19653
|
}
|
|
19530
19654
|
pending.resolve(response.data.result);
|
|
@@ -19537,6 +19661,27 @@ var MiniSidecarClient = class {
|
|
|
19537
19661
|
}
|
|
19538
19662
|
}
|
|
19539
19663
|
};
|
|
19664
|
+
function sidecarErrorToCliError(error51) {
|
|
19665
|
+
const data = isRecord5(error51.data) ? error51.data : void 0;
|
|
19666
|
+
const maybeCode = typeof data?.cliCode === "string" ? cliErrorCodeSchema.safeParse(data.cliCode) : void 0;
|
|
19667
|
+
const hint = typeof data?.recovery === "string" ? data.recovery : void 0;
|
|
19668
|
+
const retryable = typeof data?.retryable === "boolean" ? data.retryable : error51.code >= -32099 && error51.code <= -32e3;
|
|
19669
|
+
if (maybeCode?.success) {
|
|
19670
|
+
return cliError(maybeCode.data, error51.message, {
|
|
19671
|
+
data: error51,
|
|
19672
|
+
hint,
|
|
19673
|
+
retryable
|
|
19674
|
+
});
|
|
19675
|
+
}
|
|
19676
|
+
return cliError("internal.unexpected", error51.message, {
|
|
19677
|
+
data: error51,
|
|
19678
|
+
hint,
|
|
19679
|
+
retryable
|
|
19680
|
+
});
|
|
19681
|
+
}
|
|
19682
|
+
function isRecord5(value) {
|
|
19683
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19684
|
+
}
|
|
19540
19685
|
function spawnMiniSidecar(opts) {
|
|
19541
19686
|
const spawnProcess = opts.spawnProcess ?? spawn2;
|
|
19542
19687
|
const child = spawnProcess(opts.command, opts.args ?? [], {
|
|
@@ -19601,7 +19746,7 @@ async function recordViaSidecar(opts) {
|
|
|
19601
19746
|
}
|
|
19602
19747
|
}
|
|
19603
19748
|
async function startLiveRecordSession(opts) {
|
|
19604
|
-
const session = await startRecordSession({ ...opts, live:
|
|
19749
|
+
const session = await startRecordSession({ ...opts, live: false });
|
|
19605
19750
|
return {
|
|
19606
19751
|
source: session.source,
|
|
19607
19752
|
stop: async () => {
|
|
@@ -19657,16 +19802,19 @@ async function startRecordSession(opts) {
|
|
|
19657
19802
|
})
|
|
19658
19803
|
);
|
|
19659
19804
|
assertSidecarCapabilities(handshake, opts);
|
|
19805
|
+
const recordingOptions = {
|
|
19806
|
+
includeSystemAudio: opts.includeSystemAudio ?? true,
|
|
19807
|
+
includeMicrophone: opts.includeMicrophone ?? true,
|
|
19808
|
+
liveCaptions: opts.live === true,
|
|
19809
|
+
...opts.translationLanguage ? { translationLanguage: opts.translationLanguage } : {},
|
|
19810
|
+
...opts.transcriptionLanguage ? { transcriptionLanguage: opts.transcriptionLanguage } : {},
|
|
19811
|
+
...opts.title ? { title: opts.title } : {}
|
|
19812
|
+
};
|
|
19813
|
+
const preflight = await sidecar.client.getPermissionStatus({ options: recordingOptions });
|
|
19814
|
+
assertRecordingPermissions(preflight.permissions);
|
|
19660
19815
|
const started = await sidecar.client.startRecording({
|
|
19661
19816
|
account,
|
|
19662
|
-
options:
|
|
19663
|
-
includeSystemAudio: opts.includeSystemAudio ?? true,
|
|
19664
|
-
includeMicrophone: opts.includeMicrophone ?? true,
|
|
19665
|
-
liveCaptions: opts.live === true,
|
|
19666
|
-
...opts.translationLanguage ? { translationLanguage: opts.translationLanguage } : {},
|
|
19667
|
-
...opts.transcriptionLanguage ? { transcriptionLanguage: opts.transcriptionLanguage } : {},
|
|
19668
|
-
...opts.title ? { title: opts.title } : {}
|
|
19669
|
-
}
|
|
19817
|
+
options: recordingOptions
|
|
19670
19818
|
});
|
|
19671
19819
|
sessionId = started.sessionId;
|
|
19672
19820
|
latestState = started.state;
|
|
@@ -19708,6 +19856,24 @@ async function startRecordSession(opts) {
|
|
|
19708
19856
|
throw error51;
|
|
19709
19857
|
}
|
|
19710
19858
|
}
|
|
19859
|
+
function assertRecordingPermissions(permissions) {
|
|
19860
|
+
const blocked = permissions.find((permission) => permission.status !== "granted");
|
|
19861
|
+
if (!blocked) return;
|
|
19862
|
+
const label = blocked.name === "microphone" ? "Microphone" : blocked.name === "screen_recording" ? "Screen Recording" : "Recording";
|
|
19863
|
+
throw cliError("record.permission_required", `${label} permission is required before recording.`, {
|
|
19864
|
+
hint: blocked.hint,
|
|
19865
|
+
data: {
|
|
19866
|
+
code: -32020,
|
|
19867
|
+
message: `${label} permission is required before recording.`,
|
|
19868
|
+
data: {
|
|
19869
|
+
cliCode: "record.permission_required",
|
|
19870
|
+
permission: blocked.name,
|
|
19871
|
+
...blocked.hint ? { recovery: blocked.hint } : {},
|
|
19872
|
+
permissions
|
|
19873
|
+
}
|
|
19874
|
+
}
|
|
19875
|
+
});
|
|
19876
|
+
}
|
|
19711
19877
|
function assertSidecarCapabilities(handshake, opts) {
|
|
19712
19878
|
const capabilities = new Set(handshake.capabilities);
|
|
19713
19879
|
const missing = [];
|