open-agents-ai 0.184.70 → 0.184.71

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.
Files changed (2) hide show
  1. package/dist/index.js +124 -19
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11949,7 +11949,7 @@ function formatTime(seconds) {
11949
11949
  const s = Math.floor(seconds % 60);
11950
11950
  return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
11951
11951
  }
11952
- var AUDIO_EXTS, VIDEO_EXTS, _tcModule, _tcChecked, TranscribeFileTool, TranscribeUrlTool;
11952
+ var AUDIO_EXTS, VIDEO_EXTS, _tcModule, _tcChecked, TranscribeFileTool, TranscribeUrlTool, YouTubeDownloadTool;
11953
11953
  var init_transcribe_tool = __esm({
11954
11954
  "packages/execution/dist/tools/transcribe-tool.js"() {
11955
11955
  "use strict";
@@ -12267,6 +12267,90 @@ ${result.output}`,
12267
12267
  }
12268
12268
  }
12269
12269
  };
12270
+ YouTubeDownloadTool = class {
12271
+ name = "youtube_download";
12272
+ description = "Download video or audio from YouTube. Saves mp4 (video) or mp3 (audio) to the working directory. Uses yt-dlp (auto-installed). Supports youtube.com/watch, youtu.be, shorts, live URLs.";
12273
+ parameters = {
12274
+ type: "object",
12275
+ properties: {
12276
+ url: {
12277
+ type: "string",
12278
+ description: "YouTube URL (youtube.com/watch?v=..., youtu.be/..., etc.)"
12279
+ },
12280
+ format: {
12281
+ type: "string",
12282
+ enum: ["mp3", "mp4"],
12283
+ description: "Output format: 'mp3' for audio only, 'mp4' for video (default: mp3)"
12284
+ },
12285
+ output_dir: {
12286
+ type: "string",
12287
+ description: "Directory to save the file (default: current working directory)"
12288
+ }
12289
+ },
12290
+ required: ["url"]
12291
+ };
12292
+ workingDir;
12293
+ constructor(workingDir) {
12294
+ this.workingDir = workingDir;
12295
+ }
12296
+ async execute(args) {
12297
+ const start = Date.now();
12298
+ const url = String(args.url ?? "").trim();
12299
+ const format = String(args.format ?? "mp3").toLowerCase();
12300
+ const outputDir = String(args.output_dir ?? this.workingDir);
12301
+ if (!url) {
12302
+ return { success: false, output: "", error: "URL is required", durationMs: Date.now() - start };
12303
+ }
12304
+ if (!isYouTubeUrl(url)) {
12305
+ return { success: false, output: "", error: "Not a recognized YouTube URL. Supported: youtube.com/watch, youtu.be, shorts, live, embed", durationMs: Date.now() - start };
12306
+ }
12307
+ if (!ensureYtDlp()) {
12308
+ return { success: false, output: "", error: "yt-dlp not available and auto-install failed. Install manually: pip install yt-dlp", durationMs: Date.now() - start };
12309
+ }
12310
+ mkdirSync7(outputDir, { recursive: true });
12311
+ try {
12312
+ let title = "download";
12313
+ try {
12314
+ title = execSync10(`yt-dlp --get-title "${url}"`, { timeout: 15e3, stdio: "pipe" }).toString().trim().replace(/[<>:"/\\|?*]/g, "_").slice(0, 100);
12315
+ } catch {
12316
+ }
12317
+ if (format === "mp4") {
12318
+ const outPath = join19(outputDir, `${title}.mp4`);
12319
+ const outTemplate = join19(outputDir, `${title}.%(ext)s`);
12320
+ execSync10(`yt-dlp -f "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" --merge-output-format mp4 -o "${outTemplate}" "${url}"`, { timeout: 6e5, stdio: "pipe", cwd: outputDir });
12321
+ const actualPath = existsSync16(outPath) ? outPath : outTemplate.replace("%(ext)s", "mp4");
12322
+ return {
12323
+ success: true,
12324
+ output: `Downloaded video: ${actualPath}
12325
+ Title: ${title}
12326
+ Format: mp4`,
12327
+ durationMs: Date.now() - start
12328
+ };
12329
+ } else {
12330
+ const outPath = join19(outputDir, `${title}.mp3`);
12331
+ const outTemplate = join19(outputDir, `${title}.%(ext)s`);
12332
+ execSync10(`yt-dlp -x --audio-format mp3 --audio-quality 0 -o "${outTemplate}" "${url}"`, { timeout: 6e5, stdio: "pipe", cwd: outputDir });
12333
+ const actualPath = existsSync16(outPath) ? outPath : outTemplate.replace("%(ext)s", "mp3");
12334
+ return {
12335
+ success: true,
12336
+ output: `Downloaded audio: ${actualPath}
12337
+ Title: ${title}
12338
+ Format: mp3`,
12339
+ durationMs: Date.now() - start
12340
+ };
12341
+ }
12342
+ } catch (err) {
12343
+ const msg = err instanceof Error ? err.message : String(err);
12344
+ const stderr = err?.stderr?.toString?.()?.slice(0, 500) ?? "";
12345
+ return {
12346
+ success: false,
12347
+ output: "",
12348
+ error: `YouTube download failed: ${msg}${stderr ? "\n" + stderr : ""}`,
12349
+ durationMs: Date.now() - start
12350
+ };
12351
+ }
12352
+ }
12353
+ };
12270
12354
  }
12271
12355
  });
12272
12356
 
@@ -22603,6 +22687,7 @@ __export(dist_exports, {
22603
22687
  WebFetchTool: () => WebFetchTool,
22604
22688
  WebSearchTool: () => WebSearchTool,
22605
22689
  WorkingNotesTool: () => WorkingNotesTool,
22690
+ YouTubeDownloadTool: () => YouTubeDownloadTool,
22606
22691
  applyPatch: () => applyPatch,
22607
22692
  buildCompactDiff: () => buildCompactDiff,
22608
22693
  buildCustomTools: () => buildCustomTools,
@@ -45959,26 +46044,45 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`);
45959
46044
  const isArm = process.arch === "arm64" || process.arch === "arm";
45960
46045
  if (isArm) {
45961
46046
  renderInfo(" ARM device detected \u2014 installing build prerequisites then deps individually.");
46047
+ const isMac = process.platform === "darwin";
45962
46048
  try {
45963
46049
  const { spawnSync } = await import("node:child_process");
45964
- renderInfo(" System build tools needed (llvm, gcc). Requesting sudo access...");
45965
- const sudoCheck = spawnSync("sudo", ["-v"], { stdio: "inherit", timeout: 6e4 });
45966
- if (sudoCheck.status === 0) {
45967
- renderInfo(" Installing system build dependencies (this may take a minute)...");
45968
- spawnSync("sudo", [
45969
- "apt-get",
45970
- "install",
45971
- "-y",
45972
- "--no-install-recommends",
45973
- "llvm-dev",
45974
- "gcc",
45975
- "g++",
45976
- "gfortran",
45977
- "libopenblas-dev",
45978
- "libsndfile1-dev"
45979
- ], { stdio: "inherit", timeout: 12e4 });
46050
+ if (isMac) {
46051
+ renderInfo(" macOS ARM detected \u2014 installing build deps via Homebrew...");
46052
+ const brewCheck = spawnSync("which", ["brew"], { stdio: "pipe", timeout: 5e3 });
46053
+ if (brewCheck.status === 0) {
46054
+ spawnSync("brew", ["install", "llvm", "gcc", "openblas", "libsndfile"], {
46055
+ stdio: "inherit",
46056
+ timeout: 3e5
46057
+ });
46058
+ const llvmPrefix = spawnSync("brew", ["--prefix", "llvm"], { stdio: "pipe", timeout: 5e3 });
46059
+ if (llvmPrefix.stdout) {
46060
+ process.env.LLVM_CONFIG = `${llvmPrefix.stdout.toString().trim()}/bin/llvm-config`;
46061
+ }
46062
+ } else {
46063
+ renderWarning(" Homebrew not found. Install it: https://brew.sh");
46064
+ renderWarning(" Then run: brew install llvm gcc openblas libsndfile");
46065
+ }
45980
46066
  } else {
45981
- renderWarning(" sudo not available \u2014 skipping system build deps. librosa/lhotse may fail to compile.");
46067
+ renderInfo(" System build tools needed (llvm, gcc). Requesting sudo access...");
46068
+ const sudoCheck = spawnSync("sudo", ["-v"], { stdio: "inherit", timeout: 6e4 });
46069
+ if (sudoCheck.status === 0) {
46070
+ renderInfo(" Installing system build dependencies (this may take a minute)...");
46071
+ spawnSync("sudo", [
46072
+ "apt-get",
46073
+ "install",
46074
+ "-y",
46075
+ "--no-install-recommends",
46076
+ "llvm-dev",
46077
+ "gcc",
46078
+ "g++",
46079
+ "gfortran",
46080
+ "libopenblas-dev",
46081
+ "libsndfile1-dev"
46082
+ ], { stdio: "inherit", timeout: 12e4 });
46083
+ } else {
46084
+ renderWarning(" sudo not available \u2014 skipping system build deps. librosa/lhotse may fail to compile.");
46085
+ }
45982
46086
  }
45983
46087
  } catch (err) {
45984
46088
  renderWarning(` Could not install system build deps: ${err instanceof Error ? err.message : String(err)}`);
@@ -63749,9 +63853,10 @@ function buildTools(repoRoot, config, contextWindowSize) {
63749
63853
  // Skill system (AIWG skills — discovery and execution)
63750
63854
  new SkillListTool(repoRoot),
63751
63855
  new SkillExecuteTool(repoRoot),
63752
- // Transcription tools (transcribe-cli / faster-whisper)
63856
+ // Transcription + media download tools (transcribe-cli / faster-whisper / yt-dlp)
63753
63857
  new TranscribeFileTool(repoRoot),
63754
63858
  new TranscribeUrlTool(repoRoot),
63859
+ new YouTubeDownloadTool(repoRoot),
63755
63860
  // Structured file generation (CSV, JSON, Markdown, Excel-compatible)
63756
63861
  new StructuredFileTool(repoRoot),
63757
63862
  // Code sandbox (isolated code execution)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.184.70",
3
+ "version": "0.184.71",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",