open-agents-ai 0.162.0 → 0.164.0

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 +70 -19
  2. package/package.json +4 -2
package/dist/index.js CHANGED
@@ -11674,6 +11674,25 @@ async function loadTranscribeCli() {
11674
11674
  }
11675
11675
  return null;
11676
11676
  }
11677
+ function isYouTubeUrl(url) {
11678
+ return /(?:youtube\.com\/(?:watch|shorts|live|embed|v\/)|youtu\.be\/)/i.test(url);
11679
+ }
11680
+ function ensureYtDlp() {
11681
+ try {
11682
+ execSync10("yt-dlp --version", { timeout: 5e3, stdio: "pipe" });
11683
+ return true;
11684
+ } catch {
11685
+ try {
11686
+ execSync10("pip3 install --user yt-dlp 2>/dev/null || pip install --user yt-dlp 2>/dev/null", {
11687
+ timeout: 6e4,
11688
+ stdio: "pipe"
11689
+ });
11690
+ return true;
11691
+ } catch {
11692
+ return false;
11693
+ }
11694
+ }
11695
+ }
11677
11696
  function formatTime(seconds) {
11678
11697
  const m = Math.floor(seconds / 60);
11679
11698
  const s = Math.floor(seconds % 60);
@@ -11832,13 +11851,13 @@ var init_transcribe_tool = __esm({
11832
11851
  };
11833
11852
  TranscribeUrlTool = class {
11834
11853
  name = "transcribe_url";
11835
- description = "Download an audio or video file from a URL and transcribe it to text. Supports direct links to MP3, WAV, MP4, and other media files. The file is downloaded to a temp location, transcribed locally, then cleaned up.";
11854
+ description = "Download and transcribe audio/video from a URL. Supports YouTube links (youtube.com/watch?v=..., youtu.be/...) and direct media URLs (MP3, WAV, MP4, etc.). YouTube audio is extracted via yt-dlp (auto-installed). Transcription is local via faster-whisper (no cloud API).";
11836
11855
  parameters = {
11837
11856
  type: "object",
11838
11857
  properties: {
11839
11858
  url: {
11840
11859
  type: "string",
11841
- description: "URL of the audio or video file to download and transcribe"
11860
+ description: "URL to transcribe \u2014 YouTube links (youtube.com/watch?v=..., youtu.be/...) or direct media files (MP3, WAV, MP4)"
11842
11861
  },
11843
11862
  model: {
11844
11863
  type: "string",
@@ -11866,25 +11885,57 @@ var init_transcribe_tool = __esm({
11866
11885
  }
11867
11886
  const tmpDir = join19(this.workingDir, ".oa", "tmp");
11868
11887
  mkdirSync7(tmpDir, { recursive: true });
11869
- const urlPath = new URL(url).pathname;
11870
- let ext = extname3(urlPath).toLowerCase();
11871
- if (!ext || !AUDIO_EXTS.has(ext) && !VIDEO_EXTS.has(ext)) {
11872
- ext = ".mp3";
11873
- }
11874
- const tmpFile = join19(tmpDir, `download-${Date.now()}${ext}`);
11888
+ const tmpBase = join19(tmpDir, `download-${Date.now()}`);
11889
+ let tmpFile = "";
11875
11890
  try {
11876
- try {
11877
- execSync10(`curl -sL -o "${tmpFile}" "${url}"`, {
11878
- timeout: 12e4,
11879
- stdio: ["pipe", "pipe", "pipe"]
11880
- });
11881
- } catch {
11882
- execSync10(`wget -q -O "${tmpFile}" "${url}"`, {
11883
- timeout: 12e4,
11884
- stdio: ["pipe", "pipe", "pipe"]
11885
- });
11891
+ if (isYouTubeUrl(url)) {
11892
+ if (!ensureYtDlp()) {
11893
+ return {
11894
+ success: false,
11895
+ output: "",
11896
+ error: "yt-dlp not found and auto-install failed. Install manually: pip3 install yt-dlp",
11897
+ durationMs: performance.now() - start
11898
+ };
11899
+ }
11900
+ tmpFile = `${tmpBase}.mp3`;
11901
+ try {
11902
+ execSync10(`yt-dlp -x --audio-format mp3 --audio-quality 5 -o "${tmpBase}.%(ext)s" "${url}" 2>&1`, { timeout: 3e5, stdio: ["pipe", "pipe", "pipe"] });
11903
+ if (!existsSync16(tmpFile)) {
11904
+ const { readdirSync: rd } = __require("node:fs");
11905
+ const files = rd(tmpDir).filter((f) => f.startsWith(`download-`) && f !== ".gitkeep");
11906
+ const match = files.find((f) => f.includes(basename4(tmpBase)));
11907
+ if (match)
11908
+ tmpFile = join19(tmpDir, match);
11909
+ }
11910
+ } catch (dlErr) {
11911
+ const errMsg = dlErr instanceof Error ? dlErr.message : String(dlErr);
11912
+ return {
11913
+ success: false,
11914
+ output: "",
11915
+ error: `yt-dlp failed: ${errMsg.slice(0, 200)}. Is the video available and not age-restricted?`,
11916
+ durationMs: performance.now() - start
11917
+ };
11918
+ }
11919
+ } else {
11920
+ const urlPath = new URL(url).pathname;
11921
+ let ext = extname3(urlPath).toLowerCase();
11922
+ if (!ext || !AUDIO_EXTS.has(ext) && !VIDEO_EXTS.has(ext)) {
11923
+ ext = ".mp3";
11924
+ }
11925
+ tmpFile = `${tmpBase}${ext}`;
11926
+ try {
11927
+ execSync10(`curl -sL -o "${tmpFile}" "${url}"`, {
11928
+ timeout: 12e4,
11929
+ stdio: ["pipe", "pipe", "pipe"]
11930
+ });
11931
+ } catch {
11932
+ execSync10(`wget -q -O "${tmpFile}" "${url}"`, {
11933
+ timeout: 12e4,
11934
+ stdio: ["pipe", "pipe", "pipe"]
11935
+ });
11936
+ }
11886
11937
  }
11887
- if (!existsSync16(tmpFile)) {
11938
+ if (!tmpFile || !existsSync16(tmpFile)) {
11888
11939
  return {
11889
11940
  success: false,
11890
11941
  output: "",
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.162.0",
3
+ "version": "0.164.0",
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",
7
7
  "types": "./dist/index.d.ts",
8
8
  "bin": {
9
9
  "open-agents": "dist/launcher.cjs",
10
- "oa": "dist/launcher.cjs"
10
+ "oa": "dist/launcher.cjs",
11
+ "hdra": "dist/launcher.cjs",
12
+ "hydra-ai": "dist/launcher.cjs"
11
13
  },
12
14
  "files": [
13
15
  "dist",