recappi 0.1.25 → 0.1.27
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 +120 -16
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1414,12 +1414,12 @@ function statusGlyph2(status) {
|
|
|
1414
1414
|
function PermissionPreflightView({
|
|
1415
1415
|
items
|
|
1416
1416
|
}) {
|
|
1417
|
-
const allGranted = items.length > 0 && items.every((item) => item.status === "granted");
|
|
1417
|
+
const allGranted = items.length > 0 && items.every((item) => item.status === "granted" && !item.requiresProcessRestart);
|
|
1418
1418
|
return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", paddingX: 1, children: [
|
|
1419
1419
|
/* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "\u2039 Recording permissions" }),
|
|
1420
1420
|
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, flexDirection: "column", children: items.length === 0 ? /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "Checking permissions\u2026" }) : items.map((item) => {
|
|
1421
1421
|
const status = statusGlyph2(item.status);
|
|
1422
|
-
const hint = item.status === "granted" ? void 0 : item.hint ?? DEFAULT_HINTS[item.name];
|
|
1422
|
+
const hint = item.requiresProcessRestart ? "Screen Recording enabled. Run recappi record again to start." : item.status === "granted" ? void 0 : item.hint ?? DEFAULT_HINTS[item.name];
|
|
1423
1423
|
return /* @__PURE__ */ jsxs12(Box13, { flexDirection: "column", children: [
|
|
1424
1424
|
/* @__PURE__ */ jsxs12(Text13, { children: [
|
|
1425
1425
|
/* @__PURE__ */ jsx15(Text13, { color: status.color, children: status.glyph }),
|
|
@@ -1438,8 +1438,8 @@ var init_PermissionPreflightView = __esm({
|
|
|
1438
1438
|
"src/tui/PermissionPreflightView.tsx"() {
|
|
1439
1439
|
"use strict";
|
|
1440
1440
|
DEFAULT_HINTS = {
|
|
1441
|
-
"Screen Recording": "Open System Settings \u203A Privacy & Security \u203A Screen Recording, enable
|
|
1442
|
-
Microphone: "Open System Settings \u203A Privacy & Security \u203A Microphone, enable
|
|
1441
|
+
"Screen Recording": "Open System Settings \u203A Privacy & Security \u203A Screen Recording, enable Recappi Recorder, then run recappi record again.",
|
|
1442
|
+
Microphone: "Open System Settings \u203A Privacy & Security \u203A Microphone, enable Recappi Recorder, then recheck."
|
|
1443
1443
|
};
|
|
1444
1444
|
}
|
|
1445
1445
|
});
|
|
@@ -1688,7 +1688,7 @@ function recordErrorCopy(code, message) {
|
|
|
1688
1688
|
case "record.permission_required":
|
|
1689
1689
|
return {
|
|
1690
1690
|
title: "Recording needs macOS permission first.",
|
|
1691
|
-
detail: "Open System Settings > Privacy & Security, allow recording access, then
|
|
1691
|
+
detail: "Open System Settings > Privacy & Security, allow recording access, then run recappi record again.",
|
|
1692
1692
|
tone: "yellow"
|
|
1693
1693
|
};
|
|
1694
1694
|
case "record.capture_failed":
|
|
@@ -1750,8 +1750,16 @@ function permissionItemsFromRecordError(data) {
|
|
|
1750
1750
|
const sidecarData = isRecord7(sidecarError?.data) ? sidecarError.data : void 0;
|
|
1751
1751
|
const permission = typeof sidecarData?.permission === "string" ? sidecarData.permission : "";
|
|
1752
1752
|
const hint = typeof sidecarData?.recovery === "string" ? sidecarData.recovery : void 0;
|
|
1753
|
+
const requiresProcessRestart = sidecarData?.requiresProcessRestart === true || sidecarData?.requiresProcessRestart === "true";
|
|
1753
1754
|
const item = permission === "microphone" ? "Microphone" : permission === "screen_recording" ? "Screen Recording" : "Recording";
|
|
1754
|
-
return [
|
|
1755
|
+
return [
|
|
1756
|
+
{
|
|
1757
|
+
name: item,
|
|
1758
|
+
status: requiresProcessRestart ? "granted" : "denied",
|
|
1759
|
+
...hint ? { hint } : {},
|
|
1760
|
+
...requiresProcessRestart ? { requiresProcessRestart } : {}
|
|
1761
|
+
}
|
|
1762
|
+
];
|
|
1755
1763
|
}
|
|
1756
1764
|
function settingsUrlFromRecordError(data) {
|
|
1757
1765
|
const sidecarError = isRecord7(data) ? data : void 0;
|
|
@@ -17139,7 +17147,8 @@ var sidecarPermissionStatusSchema = external_exports.enum(["granted", "denied",
|
|
|
17139
17147
|
var sidecarPermissionItemSchema = external_exports.object({
|
|
17140
17148
|
name: sidecarPermissionNameSchema,
|
|
17141
17149
|
status: sidecarPermissionStatusSchema,
|
|
17142
|
-
hint: external_exports.string().optional()
|
|
17150
|
+
hint: external_exports.string().optional(),
|
|
17151
|
+
requiresProcessRestart: external_exports.boolean().optional()
|
|
17143
17152
|
});
|
|
17144
17153
|
var sidecarPermissionStatusParamsSchema = external_exports.object({
|
|
17145
17154
|
options: sidecarRecordingOptionsSchema
|
|
@@ -17289,10 +17298,11 @@ var sidecarEventSchema = external_exports.discriminatedUnion("type", [
|
|
|
17289
17298
|
external_exports.object({
|
|
17290
17299
|
type: external_exports.literal("audio.level"),
|
|
17291
17300
|
sessionId: external_exports.string(),
|
|
17292
|
-
input: external_exports.enum(["system", "microphone"
|
|
17301
|
+
input: external_exports.enum(["system", "microphone"]),
|
|
17293
17302
|
rmsDb: external_exports.number().optional(),
|
|
17294
17303
|
peakDb: external_exports.number().optional(),
|
|
17295
|
-
at: external_exports.number().int().optional()
|
|
17304
|
+
at: external_exports.number().int().optional(),
|
|
17305
|
+
atMs: external_exports.number().int().optional()
|
|
17296
17306
|
}),
|
|
17297
17307
|
external_exports.object({
|
|
17298
17308
|
type: external_exports.literal("live_caption.delta"),
|
|
@@ -20049,13 +20059,16 @@ var CLI_VERSION = readCliVersion();
|
|
|
20049
20059
|
// src/record.tsx
|
|
20050
20060
|
import { chmodSync, existsSync, statSync } from "fs";
|
|
20051
20061
|
import { createRequire as createRequire2 } from "module";
|
|
20052
|
-
import { dirname, join } from "path";
|
|
20062
|
+
import { dirname, join as join2 } from "path";
|
|
20053
20063
|
import { fileURLToPath } from "url";
|
|
20054
20064
|
import { render, useInput as useInput2 } from "ink";
|
|
20055
20065
|
init_recordingCore();
|
|
20056
20066
|
|
|
20057
20067
|
// src/sidecar.ts
|
|
20058
|
-
import { spawn as spawn2 } from "child_process";
|
|
20068
|
+
import { spawn as spawn2, spawnSync } from "child_process";
|
|
20069
|
+
import { createReadStream, createWriteStream as createWriteStream2, mkdtempSync, rmSync } from "fs";
|
|
20070
|
+
import { tmpdir } from "os";
|
|
20071
|
+
import { join } from "path";
|
|
20059
20072
|
import { createInterface } from "readline";
|
|
20060
20073
|
var MiniSidecarClient = class {
|
|
20061
20074
|
input;
|
|
@@ -20248,6 +20261,9 @@ function isRecord6(value) {
|
|
|
20248
20261
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20249
20262
|
}
|
|
20250
20263
|
function spawnMiniSidecar(opts) {
|
|
20264
|
+
if (isLaunchServicesAppCommand(opts.command)) {
|
|
20265
|
+
return spawnLaunchServicesSidecar(opts);
|
|
20266
|
+
}
|
|
20251
20267
|
const spawnProcess = opts.spawnProcess ?? spawn2;
|
|
20252
20268
|
const child = spawnProcess(opts.command, opts.args ?? [], {
|
|
20253
20269
|
env: opts.env,
|
|
@@ -20272,6 +20288,73 @@ function defaultSidecarHandshakeParams(params) {
|
|
|
20272
20288
|
...params
|
|
20273
20289
|
};
|
|
20274
20290
|
}
|
|
20291
|
+
function isLaunchServicesAppCommand(command, platform = process.platform) {
|
|
20292
|
+
return platform === "darwin" && command.endsWith(".app");
|
|
20293
|
+
}
|
|
20294
|
+
function launchServicesOpenArgs(appPath, pipes, sidecarArgs = []) {
|
|
20295
|
+
return [
|
|
20296
|
+
"-W",
|
|
20297
|
+
"-n",
|
|
20298
|
+
"-g",
|
|
20299
|
+
"--stdin",
|
|
20300
|
+
pipes.stdin,
|
|
20301
|
+
"--stdout",
|
|
20302
|
+
pipes.stdout,
|
|
20303
|
+
"--stderr",
|
|
20304
|
+
pipes.stderr,
|
|
20305
|
+
appPath,
|
|
20306
|
+
"--args",
|
|
20307
|
+
...sidecarArgs
|
|
20308
|
+
];
|
|
20309
|
+
}
|
|
20310
|
+
function spawnLaunchServicesSidecar(opts) {
|
|
20311
|
+
const spawnProcess = opts.spawnProcess ?? spawn2;
|
|
20312
|
+
const tempDir = mkdtempSync(join(tmpdir(), "recappi-sidecar-"));
|
|
20313
|
+
const pipes = {
|
|
20314
|
+
stdin: join(tempDir, "stdin.fifo"),
|
|
20315
|
+
stdout: join(tempDir, "stdout.fifo"),
|
|
20316
|
+
stderr: join(tempDir, "stderr.log")
|
|
20317
|
+
};
|
|
20318
|
+
createFifo(pipes.stdin);
|
|
20319
|
+
createFifo(pipes.stdout);
|
|
20320
|
+
const output = createReadStream(pipes.stdout);
|
|
20321
|
+
const input = createWriteStream2(pipes.stdin);
|
|
20322
|
+
const child = spawnProcess("open", launchServicesOpenArgs(opts.command, pipes, opts.args ?? []), {
|
|
20323
|
+
env: opts.env,
|
|
20324
|
+
stdio: ["ignore", "ignore", "pipe"]
|
|
20325
|
+
});
|
|
20326
|
+
const client = new MiniSidecarClient({
|
|
20327
|
+
input,
|
|
20328
|
+
output,
|
|
20329
|
+
requestTimeoutMs: opts.requestTimeoutMs
|
|
20330
|
+
});
|
|
20331
|
+
let cleaned = false;
|
|
20332
|
+
const cleanup = () => {
|
|
20333
|
+
if (cleaned) return;
|
|
20334
|
+
cleaned = true;
|
|
20335
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
20336
|
+
};
|
|
20337
|
+
child.once("exit", cleanup);
|
|
20338
|
+
child.once("error", cleanup);
|
|
20339
|
+
return {
|
|
20340
|
+
client,
|
|
20341
|
+
kill: () => {
|
|
20342
|
+
client.close();
|
|
20343
|
+
input.end();
|
|
20344
|
+
output.destroy();
|
|
20345
|
+
child.kill();
|
|
20346
|
+
cleanup();
|
|
20347
|
+
}
|
|
20348
|
+
};
|
|
20349
|
+
}
|
|
20350
|
+
function createFifo(path6) {
|
|
20351
|
+
const result = spawnSync("mkfifo", [path6], { encoding: "utf8" });
|
|
20352
|
+
if (result.status !== 0) {
|
|
20353
|
+
throw cliError("record.helper_unavailable", "Recappi recording helper could not start.", {
|
|
20354
|
+
hint: result.stderr || "Could not create the local recorder pipes. Try again."
|
|
20355
|
+
});
|
|
20356
|
+
}
|
|
20357
|
+
}
|
|
20275
20358
|
|
|
20276
20359
|
// src/record.tsx
|
|
20277
20360
|
init_LiveCaptionsScreen();
|
|
@@ -20485,7 +20568,11 @@ function normalizeSidecarMicrophones(microphones) {
|
|
|
20485
20568
|
}));
|
|
20486
20569
|
}
|
|
20487
20570
|
function assertRecordingPermissions(permissions) {
|
|
20488
|
-
const blocked = permissions.find((permission) =>
|
|
20571
|
+
const blocked = permissions.find((permission) => {
|
|
20572
|
+
if (permission.status === "granted") return false;
|
|
20573
|
+
if (permission.name === "microphone" && permission.status === "unknown") return false;
|
|
20574
|
+
return true;
|
|
20575
|
+
});
|
|
20489
20576
|
if (!blocked) return;
|
|
20490
20577
|
const label = blocked.name === "microphone" ? "Microphone" : blocked.name === "screen_recording" ? "Screen Recording" : "Recording";
|
|
20491
20578
|
throw cliError("record.permission_required", `${label} permission is required before recording.`, {
|
|
@@ -20496,6 +20583,7 @@ function assertRecordingPermissions(permissions) {
|
|
|
20496
20583
|
data: {
|
|
20497
20584
|
cliCode: "record.permission_required",
|
|
20498
20585
|
permission: blocked.name,
|
|
20586
|
+
...blocked.requiresProcessRestart ? { requiresProcessRestart: blocked.requiresProcessRestart } : {},
|
|
20499
20587
|
...blocked.hint ? { recovery: blocked.hint } : {},
|
|
20500
20588
|
permissions
|
|
20501
20589
|
}
|
|
@@ -20532,9 +20620,23 @@ function resolveSidecarCommand(opts) {
|
|
|
20532
20620
|
});
|
|
20533
20621
|
}
|
|
20534
20622
|
function ensureBundledHelperExecutable(path6) {
|
|
20623
|
+
if (process.platform === "darwin" && path6.endsWith(".app")) {
|
|
20624
|
+
const executable = darwinAppExecutablePath(path6);
|
|
20625
|
+
if (!existsSync(executable)) {
|
|
20626
|
+
throw cliError("record.helper_unavailable", "Recappi recording helper is not available.", {
|
|
20627
|
+
hint: `Expected bundled helper executable inside ${path6}. Reinstall recappi, or set ${SIDECAR_COMMAND_ENV} to a compatible helper.`
|
|
20628
|
+
});
|
|
20629
|
+
}
|
|
20630
|
+
ensureExecutableMode(executable);
|
|
20631
|
+
return path6;
|
|
20632
|
+
}
|
|
20535
20633
|
if (process.platform === "win32") return path6;
|
|
20634
|
+
ensureExecutableMode(path6);
|
|
20635
|
+
return path6;
|
|
20636
|
+
}
|
|
20637
|
+
function ensureExecutableMode(path6) {
|
|
20536
20638
|
const mode = statSync(path6).mode;
|
|
20537
|
-
if ((mode & 73) !== 0) return
|
|
20639
|
+
if ((mode & 73) !== 0) return;
|
|
20538
20640
|
try {
|
|
20539
20641
|
chmodSync(path6, mode | 493);
|
|
20540
20642
|
} catch (error51) {
|
|
@@ -20543,7 +20645,6 @@ function ensureBundledHelperExecutable(path6) {
|
|
|
20543
20645
|
hint: `Could not make bundled helper executable at ${path6}: ${message}. Reinstall recappi, or set ${SIDECAR_COMMAND_ENV} to a compatible helper.`
|
|
20544
20646
|
});
|
|
20545
20647
|
}
|
|
20546
|
-
return path6;
|
|
20547
20648
|
}
|
|
20548
20649
|
function bundledSidecarCommand(platform, arch) {
|
|
20549
20650
|
const executable = helperExecutableName(platform);
|
|
@@ -20551,16 +20652,19 @@ function bundledSidecarCommand(platform, arch) {
|
|
|
20551
20652
|
const helperPackage = helperPackageName(platform, arch);
|
|
20552
20653
|
if (helperPackage) {
|
|
20553
20654
|
const packageJson = resolveOptionalHelperPackage(helperPackage);
|
|
20554
|
-
if (packageJson) return
|
|
20655
|
+
if (packageJson) return join2(dirname(packageJson), executable);
|
|
20555
20656
|
}
|
|
20556
20657
|
const packageRoot = new URL("..", import.meta.url);
|
|
20557
20658
|
return fileURLToPath(new URL(`helpers/${platform}-${arch}/${executable}`, packageRoot));
|
|
20558
20659
|
}
|
|
20559
20660
|
function helperExecutableName(platform) {
|
|
20560
|
-
if (platform === "darwin") return SIDECAR_HELPER_NAME
|
|
20661
|
+
if (platform === "darwin") return `${SIDECAR_HELPER_NAME}.app`;
|
|
20561
20662
|
if (platform === "win32") return `${SIDECAR_HELPER_NAME}.exe`;
|
|
20562
20663
|
return null;
|
|
20563
20664
|
}
|
|
20665
|
+
function darwinAppExecutablePath(appPath) {
|
|
20666
|
+
return join2(appPath, "Contents", "MacOS", SIDECAR_HELPER_NAME);
|
|
20667
|
+
}
|
|
20564
20668
|
function helperPackageName(platform, arch) {
|
|
20565
20669
|
if (platform === "darwin" && arch === "arm64") return "recappi-helper-darwin-arm64";
|
|
20566
20670
|
return null;
|