recappi 0.1.57 → 0.1.58

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
@@ -18532,45 +18532,24 @@ function contentTypeForPath(filePath) {
18532
18532
  const fromExtension = EXT_TO_CONTENT_TYPE[path2.extname(filePath).toLowerCase()];
18533
18533
  return fromExtension ? normalizeAudioType(fromExtension) : null;
18534
18534
  }
18535
- async function collectAudioFiles(inputPath) {
18535
+ async function planAudioFile(filePath, titleOverride) {
18536
18536
  let stat;
18537
18537
  try {
18538
- stat = await fs2.stat(inputPath);
18538
+ stat = await fs2.stat(filePath);
18539
18539
  } catch {
18540
- throw cliError("input.not_found", `Path not found: ${inputPath}`);
18541
- }
18542
- if (stat.isFile()) return [inputPath];
18543
- if (!stat.isDirectory()) {
18544
- throw cliError("input.not_file", `Path is not a file or directory: ${inputPath}`);
18540
+ throw cliError("input.not_found", `Path not found: ${filePath}`);
18545
18541
  }
18546
- const found = [];
18547
- await walk(inputPath, found);
18548
- found.sort((a, b) => a.localeCompare(b));
18549
- return found;
18550
- }
18551
- async function walk(dir, found) {
18552
- const entries = await fs2.readdir(dir, { withFileTypes: true });
18553
- entries.sort((a, b) => a.name.localeCompare(b.name));
18554
- for (const entry of entries) {
18555
- const fullPath = path2.join(dir, entry.name);
18556
- if (entry.isDirectory()) {
18557
- await walk(fullPath, found);
18558
- } else if (entry.isFile() && contentTypeForPath(fullPath)) {
18559
- found.push(fullPath);
18560
- }
18542
+ if (!stat.isFile()) {
18543
+ throw cliError("input.not_file", `Path is not a file: ${filePath}`, {
18544
+ hint: "Pass one or more audio files explicitly. For a folder, expand a shell glob such as recappi upload ./recordings/*.m4a."
18545
+ });
18561
18546
  }
18562
- }
18563
- async function planAudioFile(filePath, titleOverride) {
18564
18547
  const contentType = contentTypeForPath(filePath);
18565
18548
  if (!contentType) {
18566
18549
  throw cliError("input.unsupported_audio", `Unsupported audio file: ${filePath}`, {
18567
18550
  hint: "Supported extensions: wav, mp3, aiff, aac, m4a, ogg, flac."
18568
18551
  });
18569
18552
  }
18570
- const stat = await fs2.stat(filePath);
18571
- if (!stat.isFile()) {
18572
- throw cliError("input.not_file", `Path is not a file: ${filePath}`);
18573
- }
18574
18553
  const title = titleOverride ?? path2.basename(filePath, path2.extname(filePath));
18575
18554
  const durationMs = await readDurationMs(filePath, contentType);
18576
18555
  return {
@@ -19245,13 +19224,13 @@ var RecappiApiClient = class {
19245
19224
  });
19246
19225
  }
19247
19226
  async uploadPathBatch(opts) {
19248
- const files = await collectAudioFiles(opts.inputPath);
19227
+ const files = opts.inputPaths;
19249
19228
  if (files.length === 0) {
19250
19229
  throw cliError(
19251
- "input.unsupported_audio",
19252
- `No supported audio files found: ${opts.inputPath}`,
19230
+ "usage.invalid_argument",
19231
+ "Missing upload file path.",
19253
19232
  {
19254
- hint: "Supported extensions: wav, mp3, aiff, aac, m4a, ogg, flac."
19233
+ hint: "Pass one or more audio files, e.g. recappi upload talk.m4a notes.wav."
19255
19234
  }
19256
19235
  );
19257
19236
  }
@@ -19984,18 +19963,22 @@ var COMMAND_METADATA = {
19984
19963
  },
19985
19964
  upload: {
19986
19965
  capabilities: [
19987
- "Upload a local audio file or directory",
19966
+ "Upload one or more local audio files",
19988
19967
  "Transcribe uploaded audio",
19989
19968
  "Wait for transcription to finish"
19990
19969
  ],
19991
19970
  examples: [
19992
19971
  {
19993
- description: "Upload a local audio file and wait for transcription",
19972
+ description: "Upload a file and wait for transcription",
19994
19973
  command: "recappi upload talk.m4a --transcribe --wait"
19995
19974
  },
19996
19975
  {
19997
- description: "Upload and transcribe a directory of audio files",
19998
- command: "recappi upload ./recordings --transcribe"
19976
+ description: "Upload several files at once",
19977
+ command: "recappi upload intro.m4a talk.wav qa.m4a --transcribe"
19978
+ },
19979
+ {
19980
+ description: "Upload a whole folder via shell glob",
19981
+ command: "recappi upload ./recordings/*.m4a --transcribe"
19999
19982
  },
20000
19983
  {
20001
19984
  description: "Transcribe with title and language hints",
@@ -20813,6 +20796,7 @@ function argumentDocs(command) {
20813
20796
  return args.map((arg) => ({
20814
20797
  name: arg.name(),
20815
20798
  required: arg.required === true,
20799
+ ...arg.variadic === true ? { variadic: true } : {},
20816
20800
  ...arg.description ? { description: arg.description } : {}
20817
20801
  }));
20818
20802
  }
@@ -22059,7 +22043,7 @@ async function uploadRecordedSessionAfterStop(client, data, opts = {}) {
22059
22043
  if (!artifact.audioPath) return data;
22060
22044
  try {
22061
22045
  const upload = await client.uploadPathBatch({
22062
- inputPath: artifact.audioPath,
22046
+ inputPaths: [artifact.audioPath],
22063
22047
  transcribe: true,
22064
22048
  wait: false,
22065
22049
  ...opts.title ? { title: opts.title } : {},
@@ -22197,7 +22181,7 @@ async function runCli(deps = {}) {
22197
22181
  throw cliError("input.not_found", "No local audio file is available to transcribe.");
22198
22182
  }
22199
22183
  const data = await client.uploadPathBatch({
22200
- inputPath: artifact.audioPath,
22184
+ inputPaths: [artifact.audioPath],
22201
22185
  transcribe: true,
22202
22186
  wait: false,
22203
22187
  onEvent
@@ -22276,7 +22260,7 @@ async function runCli(deps = {}) {
22276
22260
  }
22277
22261
  if (parsed.kind === "upload") {
22278
22262
  const data = await client.uploadPathBatch({
22279
- inputPath: parsed.path,
22263
+ inputPaths: parsed.paths,
22280
22264
  title: parsed.title,
22281
22265
  transcribe: parsed.transcribe,
22282
22266
  wait: parsed.wait,
@@ -22571,11 +22555,6 @@ function buildProgram({ onHelpOutput, onSelect }) {
22571
22555
  `
22572
22556
  ${commonTasksHelpText()}
22573
22557
 
22574
- Transcribe:
22575
- Local audio file recappi upload <file> --transcribe --wait
22576
- Existing cloud recording recappi recordings retranscribe <recordingId> --wait
22577
- (the "transcript" command only fetches an existing transcript by id.)
22578
-
22579
22558
  Agent mode:
22580
22559
  Non-TTY stdout defaults to JSON. Progress and human diagnostics go to stderr.
22581
22560
  Use --json for a single envelope or --jsonl for a terminal event stream.
@@ -22643,14 +22622,14 @@ Agent mode:
22643
22622
  commandName: "account status"
22644
22623
  });
22645
22624
  });
22646
- const upload = program.command("upload <file-or-dir>").description("Upload a local audio file or directory (optionally transcribe)").option("--title <title>", "recording title", parseStringOption("--title")).option("--transcribe", "start transcription after upload").option("--wait", "wait for the transcription job to reach a terminal state").option("--language <lang>", "transcription language hint", parseStringOption("--language")).option("--provider <name>", "transcription provider", parseStringOption("--provider")).option("--prompt <text>", "transcription prompt/context", parseStringOption("--prompt")).option("--force", "force upload if a conflict is retryable").addHelpText("after", commandMetadataHelpText("upload"));
22625
+ const upload = program.command("upload <files...>").description("Upload one or more local audio files (optionally transcribe)").option("--title <title>", "recording title", parseStringOption("--title")).option("--transcribe", "start transcription after upload").option("--wait", "wait for the transcription job to reach a terminal state").option("--language <lang>", "transcription language hint", parseStringOption("--language")).option("--provider <name>", "transcription provider", parseStringOption("--provider")).option("--prompt <text>", "transcription prompt/context", parseStringOption("--prompt")).option("--force", "force upload if a conflict is retryable").addHelpText("after", commandMetadataHelpText("upload"));
22647
22626
  addCommonOptions(upload);
22648
- upload.action((inputPath, opts, command) => {
22627
+ upload.action((inputPaths, opts, command) => {
22649
22628
  onSelect({
22650
22629
  kind: "upload",
22651
22630
  options: collectGlobalOptions(command),
22652
22631
  commandName: "upload",
22653
- path: inputPath,
22632
+ paths: inputPaths,
22654
22633
  ...typeof opts.title === "string" ? { title: opts.title } : {},
22655
22634
  ...opts.transcribe === true ? { transcribe: true } : {},
22656
22635
  ...opts.wait === true ? { wait: true, transcribe: true } : {},