recappi 0.1.64 → 0.1.65
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 +309 -19
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -139,7 +139,7 @@ function formatClockMs(ms) {
|
|
|
139
139
|
const ss = String(secs).padStart(2, "0");
|
|
140
140
|
return hours > 0 ? `${hours}:${mm}:${ss}` : `${mm}:${ss}`;
|
|
141
141
|
}
|
|
142
|
-
function
|
|
142
|
+
function progressBar2(fraction, width = 10) {
|
|
143
143
|
const clamped = Math.max(0, Math.min(1, fraction));
|
|
144
144
|
const filled = Math.round(clamped * width);
|
|
145
145
|
return `[${"\u2588".repeat(filled)}${"\u2591".repeat(width - filled)}]`;
|
|
@@ -200,7 +200,7 @@ function jobDetail(item) {
|
|
|
200
200
|
const fraction = transcribeFraction(item);
|
|
201
201
|
if (fraction != null) {
|
|
202
202
|
const pct2 = Math.round(fraction * 100);
|
|
203
|
-
return `${
|
|
203
|
+
return `${progressBar2(fraction)} ${String(pct2).padStart(3)}% ${formatClockMs(
|
|
204
204
|
item.processedDurationMs
|
|
205
205
|
)} / ${formatClockMs(item.recording?.durationMs)}`;
|
|
206
206
|
}
|
|
@@ -335,7 +335,7 @@ function groupedListWindow(buckets, selected, budget) {
|
|
|
335
335
|
}
|
|
336
336
|
return listWindow(selected, total, 1);
|
|
337
337
|
}
|
|
338
|
-
function
|
|
338
|
+
function formatBytes3(bytes) {
|
|
339
339
|
if (bytes == null || !Number.isFinite(bytes) || bytes < 0) return "";
|
|
340
340
|
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
341
341
|
let value = bytes;
|
|
@@ -647,16 +647,16 @@ function Usage({
|
|
|
647
647
|
] }),
|
|
648
648
|
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
649
649
|
/* @__PURE__ */ jsx5(Text3, { dimColor: true, children: "Minutes " }),
|
|
650
|
-
minutesCap != null ? /* @__PURE__ */ jsx5(Text3, { color: billing.isOverMinutes ? "red" : "cyan", children: `${
|
|
650
|
+
minutesCap != null ? /* @__PURE__ */ jsx5(Text3, { color: billing.isOverMinutes ? "red" : "cyan", children: `${progressBar2(minutesUsed / Math.max(1, minutesCap), 12)} ` }) : null,
|
|
651
651
|
/* @__PURE__ */ jsx5(Text3, { color: billing.isOverMinutes ? "red" : void 0, children: `${Math.round(minutesUsed)}` }),
|
|
652
652
|
/* @__PURE__ */ jsx5(Text3, { dimColor: true, children: ` / ${minutesCap != null ? Math.round(minutesCap) : "\u221E"} min` }),
|
|
653
653
|
/* @__PURE__ */ jsx5(Text3, { dimColor: true, children: ` (batch ${Math.round(billing.batchMinutesUsed)} \xB7 live ${Math.round(billing.realtimeMinutesUsed)})` })
|
|
654
654
|
] }),
|
|
655
655
|
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
656
656
|
/* @__PURE__ */ jsx5(Text3, { dimColor: true, children: "Storage " }),
|
|
657
|
-
storageCap != null ? /* @__PURE__ */ jsx5(Text3, { color: billing.isOverStorage ? "red" : "cyan", children: `${
|
|
658
|
-
/* @__PURE__ */ jsx5(Text3, { color: billing.isOverStorage ? "red" : void 0, children:
|
|
659
|
-
/* @__PURE__ */ jsx5(Text3, { dimColor: true, children: ` / ${storageCap != null ?
|
|
657
|
+
storageCap != null ? /* @__PURE__ */ jsx5(Text3, { color: billing.isOverStorage ? "red" : "cyan", children: `${progressBar2(billing.storageBytes / Math.max(1, storageCap), 12)} ` }) : null,
|
|
658
|
+
/* @__PURE__ */ jsx5(Text3, { color: billing.isOverStorage ? "red" : void 0, children: formatBytes3(billing.storageBytes) }),
|
|
659
|
+
/* @__PURE__ */ jsx5(Text3, { dimColor: true, children: ` / ${storageCap != null ? formatBytes3(storageCap) : "\u221E"}` })
|
|
660
660
|
] }),
|
|
661
661
|
billing.isOverMinutes || billing.isOverStorage ? /* @__PURE__ */ jsxs3(Text3, { color: "red", children: [
|
|
662
662
|
billing.isOverMinutes ? "Over minutes limit. " : "",
|
|
@@ -907,7 +907,7 @@ function PeekBody({
|
|
|
907
907
|
const style = recordingStatusStyle(item.status);
|
|
908
908
|
const meta3 = [
|
|
909
909
|
item.durationMs ? formatClockMs(item.durationMs) : null,
|
|
910
|
-
|
|
910
|
+
formatBytes3(item.sizeBytes) || null,
|
|
911
911
|
formatAge(item.createdAt, nowMs)
|
|
912
912
|
].filter(Boolean).join(" \xB7 ");
|
|
913
913
|
return /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
@@ -1108,7 +1108,7 @@ function StatusLine({
|
|
|
1108
1108
|
if (fraction != null) {
|
|
1109
1109
|
const pct2 = Math.round(fraction * 100);
|
|
1110
1110
|
return /* @__PURE__ */ jsxs10(Text11, { children: [
|
|
1111
|
-
`${
|
|
1111
|
+
`${progressBar2(fraction)} ${pct2}% ${formatClockMs(item.processedDurationMs)} / ${formatClockMs(
|
|
1112
1112
|
item.recording?.durationMs
|
|
1113
1113
|
)}`,
|
|
1114
1114
|
/* @__PURE__ */ jsx13(Text11, { dimColor: true, children: elapsed })
|
|
@@ -1169,7 +1169,7 @@ function RecordingDetailView({
|
|
|
1169
1169
|
const title = recordingTitle2(item);
|
|
1170
1170
|
const meta3 = [
|
|
1171
1171
|
item.durationMs ? formatClockMs(item.durationMs) : void 0,
|
|
1172
|
-
|
|
1172
|
+
formatBytes3(item.sizeBytes) || void 0,
|
|
1173
1173
|
item.contentType || void 0
|
|
1174
1174
|
].filter(Boolean).join(" \xB7 ");
|
|
1175
1175
|
const ready = typeof transcript === "object";
|
|
@@ -1729,7 +1729,7 @@ function RecordFrame({
|
|
|
1729
1729
|
...captions.lines.filter((l) => l.translation).map((l) => trimLead2(l.translation)),
|
|
1730
1730
|
...captions.translationPartial ? [trimLead2(captions.translationPartial)] : []
|
|
1731
1731
|
] : [];
|
|
1732
|
-
const status = telemetry.sizeBytes ?
|
|
1732
|
+
const status = telemetry.sizeBytes ? formatBytes3(telemetry.sizeBytes) : "";
|
|
1733
1733
|
const sourceLine = [telemetry.sourceLabel, telemetry.micEnabled ? "Microphone" : null, status || null].filter(Boolean).join(" \xB7 ");
|
|
1734
1734
|
return /* @__PURE__ */ jsxs15(Box16, { flexDirection: "column", paddingX: 1, height: size.rows, children: [
|
|
1735
1735
|
/* @__PURE__ */ jsxs15(Box16, { justifyContent: "space-between", children: [
|
|
@@ -20235,13 +20235,240 @@ ${lines.join("\n")}
|
|
|
20235
20235
|
` : "";
|
|
20236
20236
|
}
|
|
20237
20237
|
|
|
20238
|
+
// src/progressStepper.ts
|
|
20239
|
+
var STEP_DEFS = [
|
|
20240
|
+
{ key: "check", label: "Check" },
|
|
20241
|
+
{ key: "upload", label: "Upload" },
|
|
20242
|
+
{ key: "transcribe", label: "Transcribe" },
|
|
20243
|
+
{ key: "done", label: "Done" }
|
|
20244
|
+
];
|
|
20245
|
+
var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
20246
|
+
var BAR_WIDTH = 16;
|
|
20247
|
+
var LABEL_WIDTH = 11;
|
|
20248
|
+
function createStepperModel() {
|
|
20249
|
+
return {
|
|
20250
|
+
steps: STEP_DEFS.map((d) => ({ ...d, status: "pending", detail: "" })),
|
|
20251
|
+
finished: false
|
|
20252
|
+
};
|
|
20253
|
+
}
|
|
20254
|
+
function isStepperEvent(event) {
|
|
20255
|
+
if (event.command !== "upload") return false;
|
|
20256
|
+
if (event.type === "started") return true;
|
|
20257
|
+
return typeof event.status === "string";
|
|
20258
|
+
}
|
|
20259
|
+
function cloneModel(model) {
|
|
20260
|
+
return {
|
|
20261
|
+
steps: model.steps.map((s) => ({ ...s })),
|
|
20262
|
+
...model.transcribeStartMs != null ? { transcribeStartMs: model.transcribeStartMs } : {},
|
|
20263
|
+
finished: model.finished
|
|
20264
|
+
};
|
|
20265
|
+
}
|
|
20266
|
+
function applyStepperEvent(model, event, nowMs) {
|
|
20267
|
+
const next = cloneModel(model);
|
|
20268
|
+
const step = (key) => next.steps.find((s) => s.key === key);
|
|
20269
|
+
const markDone = (key) => {
|
|
20270
|
+
const s = step(key);
|
|
20271
|
+
if (s.status !== "failed") {
|
|
20272
|
+
s.status = "done";
|
|
20273
|
+
s.percent = void 0;
|
|
20274
|
+
}
|
|
20275
|
+
};
|
|
20276
|
+
const startTranscribeClock = () => {
|
|
20277
|
+
if (next.transcribeStartMs == null) next.transcribeStartMs = nowMs;
|
|
20278
|
+
};
|
|
20279
|
+
switch (event.status) {
|
|
20280
|
+
case "checking_audio":
|
|
20281
|
+
step("check").status = "active";
|
|
20282
|
+
break;
|
|
20283
|
+
case "starting_upload": {
|
|
20284
|
+
markDone("check");
|
|
20285
|
+
const file2 = fileFromEvent(event);
|
|
20286
|
+
if (file2) step("check").detail = file2;
|
|
20287
|
+
step("upload").status = "active";
|
|
20288
|
+
step("upload").detail = "Starting\u2026";
|
|
20289
|
+
break;
|
|
20290
|
+
}
|
|
20291
|
+
case "uploading":
|
|
20292
|
+
step("upload").status = "active";
|
|
20293
|
+
step("upload").detail = "";
|
|
20294
|
+
if (typeof event.percent === "number") step("upload").percent = event.percent;
|
|
20295
|
+
break;
|
|
20296
|
+
case "finishing_upload":
|
|
20297
|
+
step("upload").status = "active";
|
|
20298
|
+
step("upload").detail = "Finalizing";
|
|
20299
|
+
step("upload").percent = 100;
|
|
20300
|
+
break;
|
|
20301
|
+
case "uploaded":
|
|
20302
|
+
markDone("upload");
|
|
20303
|
+
step("upload").detail = recordingUrl(event) ?? "Uploaded";
|
|
20304
|
+
break;
|
|
20305
|
+
case "starting_transcription":
|
|
20306
|
+
step("transcribe").status = "active";
|
|
20307
|
+
step("transcribe").detail = "Starting\u2026";
|
|
20308
|
+
startTranscribeClock();
|
|
20309
|
+
break;
|
|
20310
|
+
case "queued":
|
|
20311
|
+
step("transcribe").status = "active";
|
|
20312
|
+
step("transcribe").detail = "Queued";
|
|
20313
|
+
startTranscribeClock();
|
|
20314
|
+
break;
|
|
20315
|
+
case "running":
|
|
20316
|
+
step("transcribe").status = "active";
|
|
20317
|
+
startTranscribeClock();
|
|
20318
|
+
if (typeof event.percent === "number") {
|
|
20319
|
+
step("transcribe").percent = event.percent;
|
|
20320
|
+
step("transcribe").detail = "";
|
|
20321
|
+
} else {
|
|
20322
|
+
step("transcribe").percent = void 0;
|
|
20323
|
+
step("transcribe").detail = "Transcribing\u2026";
|
|
20324
|
+
}
|
|
20325
|
+
break;
|
|
20326
|
+
case "succeeded":
|
|
20327
|
+
markDone("transcribe");
|
|
20328
|
+
markDone("done");
|
|
20329
|
+
if (event.transcriptId) {
|
|
20330
|
+
step("done").detail = `\u2192 recappi transcript get ${event.transcriptId}`;
|
|
20331
|
+
}
|
|
20332
|
+
next.finished = true;
|
|
20333
|
+
break;
|
|
20334
|
+
case "failed":
|
|
20335
|
+
markActiveFailed(next, event.message);
|
|
20336
|
+
break;
|
|
20337
|
+
default:
|
|
20338
|
+
if (event.type === "started") step("check").status = "active";
|
|
20339
|
+
break;
|
|
20340
|
+
}
|
|
20341
|
+
return next;
|
|
20342
|
+
}
|
|
20343
|
+
function markStepperFailed(model, message) {
|
|
20344
|
+
const next = cloneModel(model);
|
|
20345
|
+
markActiveFailed(next, message);
|
|
20346
|
+
return next;
|
|
20347
|
+
}
|
|
20348
|
+
function completeStepperModel(model, next) {
|
|
20349
|
+
const m = cloneModel(model);
|
|
20350
|
+
const transcribe = m.steps.find((s) => s.key === "transcribe");
|
|
20351
|
+
if (transcribe.status === "pending") {
|
|
20352
|
+
transcribe.status = "skipped";
|
|
20353
|
+
transcribe.detail = "no --transcribe";
|
|
20354
|
+
}
|
|
20355
|
+
for (const s of m.steps) {
|
|
20356
|
+
if (s.status === "active" || s.status === "pending") s.status = "done";
|
|
20357
|
+
s.percent = void 0;
|
|
20358
|
+
}
|
|
20359
|
+
const done = m.steps.find((s) => s.key === "done");
|
|
20360
|
+
if (next?.transcriptId) done.detail = `\u2192 recappi transcript get ${next.transcriptId}`;
|
|
20361
|
+
else if (next?.recordingId) done.detail = `\u2192 recappi recordings get ${next.recordingId}`;
|
|
20362
|
+
m.finished = true;
|
|
20363
|
+
return m;
|
|
20364
|
+
}
|
|
20365
|
+
function markActiveFailed(model, message) {
|
|
20366
|
+
const active = model.steps.find((s) => s.status === "active");
|
|
20367
|
+
const target = active ?? model.steps.find((s) => s.status === "pending");
|
|
20368
|
+
if (target) {
|
|
20369
|
+
target.status = "failed";
|
|
20370
|
+
if (message) target.detail = message;
|
|
20371
|
+
}
|
|
20372
|
+
model.finished = true;
|
|
20373
|
+
}
|
|
20374
|
+
function formatStepperLines(model, nowMs, spinnerFrame, color) {
|
|
20375
|
+
return model.steps.map((s) => {
|
|
20376
|
+
const marker = markerFor(s, spinnerFrame);
|
|
20377
|
+
const label = s.label.padEnd(LABEL_WIDTH);
|
|
20378
|
+
let detail = s.detail;
|
|
20379
|
+
if (s.status === "active" && typeof s.percent === "number") {
|
|
20380
|
+
detail = `${progressBar(s.percent)} ${clampPercent2(s.percent)}%`;
|
|
20381
|
+
}
|
|
20382
|
+
if (s.key === "transcribe" && s.status === "active" && model.transcribeStartMs != null) {
|
|
20383
|
+
const elapsed = formatElapsed(Math.max(0, nowMs - model.transcribeStartMs));
|
|
20384
|
+
detail = detail ? `${detail} \xB7 ${elapsed}` : elapsed;
|
|
20385
|
+
}
|
|
20386
|
+
const body = ` ${marker} ${label}${detail}`.trimEnd();
|
|
20387
|
+
return color ? colorize(s.status, marker, body) : body;
|
|
20388
|
+
});
|
|
20389
|
+
}
|
|
20390
|
+
function markerFor(step, spinnerFrame) {
|
|
20391
|
+
switch (step.status) {
|
|
20392
|
+
case "done":
|
|
20393
|
+
return "\u2713";
|
|
20394
|
+
case "failed":
|
|
20395
|
+
return "\u2717";
|
|
20396
|
+
case "active":
|
|
20397
|
+
return SPINNER[spinnerFrame % SPINNER.length];
|
|
20398
|
+
case "skipped":
|
|
20399
|
+
return "\xB7";
|
|
20400
|
+
default:
|
|
20401
|
+
return "\u25CB";
|
|
20402
|
+
}
|
|
20403
|
+
}
|
|
20404
|
+
function colorize(status, marker, line) {
|
|
20405
|
+
const code = status === "done" ? "32" : status === "failed" ? "31" : status === "active" ? "36" : "90";
|
|
20406
|
+
const colored = `\x1B[${code}m${marker}\x1B[0m`;
|
|
20407
|
+
return line.replace(marker, colored);
|
|
20408
|
+
}
|
|
20409
|
+
function progressBar(percent) {
|
|
20410
|
+
const p = clampPercent2(percent);
|
|
20411
|
+
const filled = Math.round(p / 100 * BAR_WIDTH);
|
|
20412
|
+
return "\u2588".repeat(filled) + "\u2591".repeat(BAR_WIDTH - filled);
|
|
20413
|
+
}
|
|
20414
|
+
function clampPercent2(percent) {
|
|
20415
|
+
return Math.max(0, Math.min(100, Math.round(percent)));
|
|
20416
|
+
}
|
|
20417
|
+
function fileFromEvent(event) {
|
|
20418
|
+
const data = event.data;
|
|
20419
|
+
if (!data || typeof data !== "object") return void 0;
|
|
20420
|
+
const file2 = data.file;
|
|
20421
|
+
if (!file2 || typeof file2 !== "object") return void 0;
|
|
20422
|
+
const f = file2;
|
|
20423
|
+
const parts = [];
|
|
20424
|
+
if (typeof f.title === "string" && f.title) parts.push(f.title);
|
|
20425
|
+
if (typeof f.sizeBytes === "number") parts.push(formatBytes(f.sizeBytes));
|
|
20426
|
+
if (typeof f.durationMs === "number") parts.push(formatMediaDuration(f.durationMs));
|
|
20427
|
+
return parts.length ? parts.join(" \xB7 ") : void 0;
|
|
20428
|
+
}
|
|
20429
|
+
function recordingUrl(event) {
|
|
20430
|
+
if (typeof event.message === "string" && event.message.includes("/recordings/")) {
|
|
20431
|
+
const idx = event.message.indexOf("http");
|
|
20432
|
+
if (idx >= 0) return event.message.slice(idx);
|
|
20433
|
+
}
|
|
20434
|
+
if (event.origin && event.recordingId) {
|
|
20435
|
+
return `${event.origin.replace(/\/+$/, "")}/recordings/${event.recordingId}`;
|
|
20436
|
+
}
|
|
20437
|
+
return void 0;
|
|
20438
|
+
}
|
|
20439
|
+
function formatBytes(bytes) {
|
|
20440
|
+
if (bytes >= 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
20441
|
+
if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
20442
|
+
if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
20443
|
+
return `${bytes} B`;
|
|
20444
|
+
}
|
|
20445
|
+
function formatMediaDuration(ms) {
|
|
20446
|
+
const totalSec = Math.round(ms / 1e3);
|
|
20447
|
+
const h = Math.floor(totalSec / 3600);
|
|
20448
|
+
const m = Math.floor(totalSec % 3600 / 60);
|
|
20449
|
+
const s = totalSec % 60;
|
|
20450
|
+
if (h > 0) return `${h}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
20451
|
+
return `${m}:${String(s).padStart(2, "0")}`;
|
|
20452
|
+
}
|
|
20453
|
+
function formatElapsed(ms) {
|
|
20454
|
+
const totalSec = Math.floor(ms / 1e3);
|
|
20455
|
+
const h = Math.floor(totalSec / 3600);
|
|
20456
|
+
const m = Math.floor(totalSec % 3600 / 60);
|
|
20457
|
+
const s = totalSec % 60;
|
|
20458
|
+
const clock = h > 0 ? `${h}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}` : `${m}:${String(s).padStart(2, "0")}`;
|
|
20459
|
+
return `${clock} elapsed`;
|
|
20460
|
+
}
|
|
20461
|
+
|
|
20238
20462
|
// src/render.ts
|
|
20239
20463
|
function createHumanProgressState(interactive) {
|
|
20240
20464
|
return {
|
|
20241
20465
|
interactive,
|
|
20242
20466
|
activeLineLength: 0,
|
|
20243
20467
|
lastLineByScope: /* @__PURE__ */ new Map(),
|
|
20244
|
-
lastUploadBucketByScope: /* @__PURE__ */ new Map()
|
|
20468
|
+
lastUploadBucketByScope: /* @__PURE__ */ new Map(),
|
|
20469
|
+
stepperLinesDrawn: 0,
|
|
20470
|
+
spinnerFrame: 0,
|
|
20471
|
+
stepperShown: false
|
|
20245
20472
|
};
|
|
20246
20473
|
}
|
|
20247
20474
|
function renderSuccess(command, data, opts) {
|
|
@@ -20263,6 +20490,7 @@ function renderSuccess(command, data, opts) {
|
|
|
20263
20490
|
renderEnvelope(envelope, opts);
|
|
20264
20491
|
return;
|
|
20265
20492
|
}
|
|
20493
|
+
finalizeStepperSuccess(command, filtered, opts);
|
|
20266
20494
|
finishHumanProgress(opts);
|
|
20267
20495
|
renderHumanSuccess(command, filtered, opts);
|
|
20268
20496
|
}
|
|
@@ -20291,6 +20519,7 @@ function renderFailure(command, error51, opts, data) {
|
|
|
20291
20519
|
renderEnvelope(envelope, opts);
|
|
20292
20520
|
return;
|
|
20293
20521
|
}
|
|
20522
|
+
if (finalizeStepperFailure(command, error51, opts, data)) return;
|
|
20294
20523
|
finishHumanProgress(opts);
|
|
20295
20524
|
opts.stderr(`recappi: ${error51.message}
|
|
20296
20525
|
`);
|
|
@@ -20316,6 +20545,10 @@ function renderEvent(event, opts) {
|
|
|
20316
20545
|
return;
|
|
20317
20546
|
}
|
|
20318
20547
|
if ((event.type === "started" || event.type === "progress") && opts.mode === "human") {
|
|
20548
|
+
if (opts.progress?.interactive && isStepperEvent(event)) {
|
|
20549
|
+
renderStepperEvent(event, opts);
|
|
20550
|
+
return;
|
|
20551
|
+
}
|
|
20319
20552
|
const line = formatHumanProgress(event, opts);
|
|
20320
20553
|
if (line) {
|
|
20321
20554
|
if (isPersistentProgressEvent(event)) writePersistentHumanProgress(line, opts);
|
|
@@ -20323,6 +20556,56 @@ function renderEvent(event, opts) {
|
|
|
20323
20556
|
}
|
|
20324
20557
|
}
|
|
20325
20558
|
}
|
|
20559
|
+
function renderStepperEvent(event, opts) {
|
|
20560
|
+
const state = opts.progress;
|
|
20561
|
+
if (!state) return;
|
|
20562
|
+
if (!state.stepper) state.stepper = createStepperModel();
|
|
20563
|
+
state.stepper = applyStepperEvent(state.stepper, event, Date.now());
|
|
20564
|
+
state.spinnerFrame += 1;
|
|
20565
|
+
drawStepperBlock(state, opts);
|
|
20566
|
+
}
|
|
20567
|
+
function drawStepperBlock(state, opts) {
|
|
20568
|
+
if (!state.stepper) return;
|
|
20569
|
+
const lines = formatStepperLines(state.stepper, Date.now(), state.spinnerFrame, true);
|
|
20570
|
+
let out = "";
|
|
20571
|
+
if (state.stepperLinesDrawn > 0) out += `\x1B[${state.stepperLinesDrawn}A`;
|
|
20572
|
+
for (const line of lines) out += `\x1B[2K${line}
|
|
20573
|
+
`;
|
|
20574
|
+
opts.stderr(out);
|
|
20575
|
+
state.stepperLinesDrawn = lines.length;
|
|
20576
|
+
state.stepperShown = true;
|
|
20577
|
+
}
|
|
20578
|
+
function finalizeStepperSuccess(command, data, opts) {
|
|
20579
|
+
const state = opts.progress;
|
|
20580
|
+
if (!state?.stepper || state.stepperLinesDrawn === 0 || command !== "upload") return;
|
|
20581
|
+
const success2 = firstUploadSuccess(data);
|
|
20582
|
+
state.stepper = completeStepperModel(state.stepper, success2);
|
|
20583
|
+
drawStepperBlock(state, opts);
|
|
20584
|
+
}
|
|
20585
|
+
function firstUploadSuccess(data) {
|
|
20586
|
+
if (!isUploadBatch(data) || data.successes.length === 0) return void 0;
|
|
20587
|
+
const s = data.successes[0];
|
|
20588
|
+
return {
|
|
20589
|
+
...s.transcriptId ? { transcriptId: s.transcriptId } : {},
|
|
20590
|
+
...s.recordingId ? { recordingId: s.recordingId } : {}
|
|
20591
|
+
};
|
|
20592
|
+
}
|
|
20593
|
+
function finalizeStepperFailure(command, error51, opts, data) {
|
|
20594
|
+
const state = opts.progress;
|
|
20595
|
+
if (!state?.stepper || state.stepperLinesDrawn === 0) return false;
|
|
20596
|
+
state.stepper = markStepperFailed(state.stepper, stepperFailureDetail(command, error51, data));
|
|
20597
|
+
drawStepperBlock(state, opts);
|
|
20598
|
+
state.stepperLinesDrawn = 0;
|
|
20599
|
+
state.stepper = void 0;
|
|
20600
|
+
return true;
|
|
20601
|
+
}
|
|
20602
|
+
function stepperFailureDetail(command, error51, data) {
|
|
20603
|
+
if (command === "upload" && isUploadBatch(data) && data.failures.length > 0) {
|
|
20604
|
+
const first = data.failures[0].error;
|
|
20605
|
+
return `${first.message} (${first.code})`;
|
|
20606
|
+
}
|
|
20607
|
+
return `${error51.message} (${error51.code})`;
|
|
20608
|
+
}
|
|
20326
20609
|
function renderEnvelope(envelope, opts) {
|
|
20327
20610
|
const parsed = cliEnvelopeSchema.parse(envelope);
|
|
20328
20611
|
opts.stdout(`${stableStringify(parsed, opts.compact === true)}
|
|
@@ -20372,7 +20655,7 @@ function renderHumanSuccess(command, data, opts) {
|
|
|
20372
20655
|
}
|
|
20373
20656
|
if (typeof billing.storageBytes === "number") {
|
|
20374
20657
|
const cap = formatNullableCap(billing.storageCapBytes, "bytes");
|
|
20375
|
-
opts.stdout(` storage: ${
|
|
20658
|
+
opts.stdout(` storage: ${formatBytes2(billing.storageBytes)} / ${cap}
|
|
20376
20659
|
`);
|
|
20377
20660
|
}
|
|
20378
20661
|
const localStore = isRecord4(data.localStore) ? data.localStore : {};
|
|
@@ -20434,7 +20717,7 @@ Next cursor: ${data.nextCursor}
|
|
|
20434
20717
|
if (typeof data.durationMs === "number")
|
|
20435
20718
|
opts.stdout(` duration: ${formatDurationMs(data.durationMs)}
|
|
20436
20719
|
`);
|
|
20437
|
-
if (typeof data.sizeBytes === "number") opts.stdout(` size: ${
|
|
20720
|
+
if (typeof data.sizeBytes === "number") opts.stdout(` size: ${formatBytes2(data.sizeBytes)}
|
|
20438
20721
|
`);
|
|
20439
20722
|
if (typeof data.activeTranscriptId === "string") {
|
|
20440
20723
|
opts.stdout(` activeTranscriptId: ${data.activeTranscriptId}
|
|
@@ -20483,6 +20766,7 @@ Next:
|
|
|
20483
20766
|
return;
|
|
20484
20767
|
}
|
|
20485
20768
|
if (command === "upload" && isUploadBatch(data)) {
|
|
20769
|
+
if (opts.progress?.stepperShown && data.failures.length === 0) return;
|
|
20486
20770
|
if (data.successes.length > 0) {
|
|
20487
20771
|
opts.stdout(uploadSuccessHeading(data.successes));
|
|
20488
20772
|
}
|
|
@@ -20708,7 +20992,13 @@ function writePersistentHumanProgress(line, opts) {
|
|
|
20708
20992
|
}
|
|
20709
20993
|
function finishHumanProgress(opts) {
|
|
20710
20994
|
const state = opts.progress;
|
|
20711
|
-
if (!state
|
|
20995
|
+
if (!state) return;
|
|
20996
|
+
if (state.stepperLinesDrawn > 0) {
|
|
20997
|
+
state.stepperLinesDrawn = 0;
|
|
20998
|
+
state.stepper = void 0;
|
|
20999
|
+
return;
|
|
21000
|
+
}
|
|
21001
|
+
if (!state.interactive || state.activeLineLength === 0) return;
|
|
20712
21002
|
opts.stderr("\n");
|
|
20713
21003
|
state.activeLineLength = 0;
|
|
20714
21004
|
}
|
|
@@ -20801,7 +21091,7 @@ function numberText(value) {
|
|
|
20801
21091
|
function formatDurationMs(ms) {
|
|
20802
21092
|
return formatClock(ms / 1e3);
|
|
20803
21093
|
}
|
|
20804
|
-
function
|
|
21094
|
+
function formatBytes2(bytes) {
|
|
20805
21095
|
if (bytes < 1024) return `${bytes} B`;
|
|
20806
21096
|
const units = ["KB", "MB", "GB", "TB"];
|
|
20807
21097
|
let value = bytes / 1024;
|
|
@@ -20816,7 +21106,7 @@ function formatBytes(bytes) {
|
|
|
20816
21106
|
function formatNullableCap(value, unit) {
|
|
20817
21107
|
if (value === null || value === void 0) return "Unlimited";
|
|
20818
21108
|
if (typeof value !== "number" || !Number.isFinite(value)) return "Unlimited";
|
|
20819
|
-
return unit === "bytes" ?
|
|
21109
|
+
return unit === "bytes" ? formatBytes2(value) : String(value);
|
|
20820
21110
|
}
|
|
20821
21111
|
function formatClock(seconds) {
|
|
20822
21112
|
const total = Math.max(0, Math.floor(seconds));
|
|
@@ -21475,7 +21765,7 @@ function RecordingHeroScreen({
|
|
|
21475
21765
|
const phase = stoppedPhase(artifact);
|
|
21476
21766
|
const meta3 = [
|
|
21477
21767
|
telemetry.durationMs != null ? formatClockMs(telemetry.durationMs) : null,
|
|
21478
|
-
|
|
21768
|
+
formatBytes3(telemetry.sizeBytes) || null
|
|
21479
21769
|
].filter(Boolean).join(" \xB7 ");
|
|
21480
21770
|
const saved = artifact?.uploadStatus === "uploaded" ? "\u2713 Saved to Recappi Cloud" : "\u2713 Saved to your Mac";
|
|
21481
21771
|
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
|
|
@@ -21510,7 +21800,7 @@ function RecordingHeroScreen({
|
|
|
21510
21800
|
const starting = telemetry.status === "starting" || telemetry.status === "stopping";
|
|
21511
21801
|
const badge = paused ? "\u23F8 PAUSED" : starting ? "\u2026" : "\u23FA REC";
|
|
21512
21802
|
const meterW = Math.max(10, Math.min(72, innerWidth - 20));
|
|
21513
|
-
const sizeStr = telemetry.sizeBytes ?
|
|
21803
|
+
const sizeStr = telemetry.sizeBytes ? formatBytes3(telemetry.sizeBytes) : "";
|
|
21514
21804
|
const context = [telemetry.sourceLabel, telemetry.micEnabled ? "Microphone" : null, sizeStr || null].filter(Boolean).join(" \xB7 ");
|
|
21515
21805
|
const waveRows = waveRowsFor(size.rows);
|
|
21516
21806
|
const meterBlockRows = (telemetry.micEnabled ? 2 : 1) * (waveRows + 1) + (telemetry.micEnabled ? 1 : 0);
|