{"id":"187c7b5d-0a3a-45b1-b91e-07d314f7b09a","entityType":"agent","slug":"clawhub-dynamicsalex-internet-radio-music-player","name":"Internet Radio Music Player","canonicalUrl":"https://www.xpersona.co/agent/clawhub-dynamicsalex-internet-radio-music-player","canonicalPath":"/agent/clawhub-dynamicsalex-internet-radio-music-player","generatedAt":"2026-10-11T10:52:47.851Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T07:30:40.191Z","emptyReason":null},"description":"Plays internet radio streams via Foobar2000 based on your mood, selecting a genre and stream from the Internet Radio Music DB with control and history support.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.1K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s17f1j49zad5p9q8z82sw3me2d87esv0:internet-radio-music-player","sourceUrl":"https://clawhub.ai/dynamicsalex/internet-radio-music-player","homepage":"https://clawhub.ai/dynamicsalex/skills/internet-radio-music-player","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/dynamicsalex/internet-radio-music-player","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/dynamicsalex/skills/internet-radio-music-player","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":61,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Internet Radio Music Player technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T07:30:40.191Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T07:30:40.191Z","emptyReason":null},"stars":null,"forks":null,"downloads":1123,"packageName":null,"latestVersion":"2.5.3","tractionLabel":"1.1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T07:30:40.126Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T07:30:40.191Z","lastCrawledAt":"2026-10-11T07:30:40.126Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T07:30:40.126Z","lastVerifiedAt":null,"highlights":[{"version":"2.5.3","createdAt":"2026-06-05T11:50:06.082Z","changelog":"- Removed the file: skill-card.md - No changes to code or features; only documentation file removal.","fileCount":6,"zipByteSize":16453},{"version":"2.5.2","createdAt":"2026-06-05T11:03:44.817Z","changelog":"## internet-radio-music-player v2.5.2 - Metadata file updated. - Removed skill-card.md file to simplify documentation management.","fileCount":6,"zipByteSize":16471},{"version":"2.5.1","createdAt":"2026-05-29T11:27:53.975Z","changelog":"v2.5.1: Fixed plugin installation command — use 'clawhub:internet-radio-music-webui' (with clawhub: prefix) instead of plain name. Without the prefix, openclaw searches npm and fails to find the plugin.","fileCount":6,"zipByteSize":16465},{"version":"2.5.0","createdAt":"2026-05-29T11:13:22.799Z","changelog":"v2.5.0: Added information about the internet-radio-music-webui plugin — the easiest way to manage playback and stream database. Plugin provides web panel with playback controls, mood-based genre selector, and DB management (stats, list, check, rebuild). Both internet-radio-music-db skill and this skill are required for the plugin to work.","fileCount":6,"zipByteSize":16506},{"version":"2.4.0","createdAt":"2026-05-29T09:00:10.563Z","changelog":"v2.4.0: Smart play after stop — auto-resume. If playback was stopped via stop, pressing play without specifying a mood/genre now resumes the last played stream from history instead of starting a new random one. State tracks Stopped flag to distinguish between never played and explicitly stopped. Changed --mood default from ambient to None for proper detection.","fileCount":6,"zipByteSize":16035},{"version":"2.3.1","createdAt":"2026-05-27T16:37:09.469Z","changelog":"v2.3.1: Added English summary field to fix Russian description on ClawHub.","fileCount":5,"zipByteSize":14854},{"version":"2.3.0","createdAt":"2026-05-27T16:26:40.721Z","changelog":"v2.3.0: Removed random.shuffle — streams now always play in relevance order (pure genre first). Full English translation of SKILL.md.","fileCount":5,"zipByteSize":14749},{"version":"2.2.0","createdAt":"2026-05-27T10:55:48.268Z","changelog":"v2.2.0: 4-уровневая сортировка (genre match > position > extra > speed), next выбирает из базы по жанру, исправлен stop/play в Foobar2000, обработан пустой genres","fileCount":6,"zipByteSize":16510}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17f1j49zad5p9q8z82sw3me2d87esv0:internet-radio-music-player","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17f1j49zad5p9q8z82sw3me2d87esv0:internet-radio-music-player` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/dynamicsalex/internet-radio-music-player before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-dynamicsalex-internet-radio-music-player/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-dynamicsalex-internet-radio-music-player/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-dynamicsalex-internet-radio-music-player/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-dynamicsalex-internet-radio-music-player/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-dynamicsalex-internet-radio-music-player/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-dynamicsalex-internet-radio-music-player/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T10:52:47.847Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-dynamicsalex-internet-radio-music-player/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-dynamicsalex-internet-radio-music-player/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-dynamicsalex-internet-radio-music-player/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-dynamicsalex-internet-radio-music-player/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T07:30:40.191Z","emptyReason":null},"readme":"Skill: Internet Radio Music Player\n\nOwner: dynamicsalex\n\nSummary: Plays internet radio streams via Foobar2000 based on your mood, selecting a genre and stream from the Internet Radio Music DB with control and history support.\n\nTags: foobar2000:2.0.0, internet-radio:2.0.0, latest:2.5.3, music:2.0.0, player:2.0.0, radio:2.0.0\n\nVersion history:\n\nv2.5.3 | 2026-06-05T11:50:06.082Z | auto\n\n- Removed the file: skill-card.md\n- No changes to code or features; only documentation file removal.\n\nv2.5.2 | 2026-06-05T11:03:44.817Z | auto\n\n## internet-radio-music-player v2.5.2\n\n- Metadata file updated.\n- Removed skill-card.md file to simplify documentation management.\n\nv2.5.1 | 2026-05-29T11:27:53.975Z | user\n\nv2.5.1: Fixed plugin installation command — use 'clawhub:internet-radio-music-webui' (with clawhub: prefix) instead of plain name. Without the prefix, openclaw searches npm and fails to find the plugin.\n\nv2.5.0 | 2026-05-29T11:13:22.799Z | user\n\nv2.5.0: Added information about the internet-radio-music-webui plugin — the easiest way to manage playback and stream database. Plugin provides web panel with playback controls, mood-based genre selector, and DB management (stats, list, check, rebuild). Both internet-radio-music-db skill and this skill are required for the plugin to work.\n\nv2.4.0 | 2026-05-29T09:00:10.563Z | user\n\nv2.4.0: Smart play after stop — auto-resume. If playback was stopped via stop, pressing play without specifying a mood/genre now resumes the last played stream from history instead of starting a new random one. State tracks Stopped flag to distinguish between never played and explicitly stopped. Changed --mood default from ambient to None for proper detection.\n\nv2.3.1 | 2026-05-27T16:37:09.469Z | user\n\nv2.3.1: Added English summary field to fix Russian description on ClawHub.\n\nv2.3.0 | 2026-05-27T16:26:40.721Z | user\n\nv2.3.0: Removed random.shuffle — streams now always play in relevance order (pure genre first). Full English translation of SKILL.md.\n\nv2.2.0 | 2026-05-27T10:55:48.268Z | user\n\nv2.2.0: 4-уровневая сортировка (genre match > position > extra > speed), next выбирает из базы по жанру, исправлен stop/play в Foobar2000, обработан пустой genres\n\nv2.1.0 | 2026-05-27T09:57:15.256Z | user\n\nv2.1.0: умная сортировка потоков по релевантности жанра (позиция в genres, количество лишних жанров, скорость), автоопределение пути Foobar2000, поддержка русского кантри, добавлен lounge\n\nv2.0.0 | 2026-05-26T17:01:31.505Z | user\n\nv2.0: Удалены неиспользуемые ps1-скрипты. Добавлено явное указание на обязательность Internet Radio Music DB. Обновлено описание с актуальными путями и командами. Убраны ссылки на PowerShell.\n\nv1.6.0 | 2026-05-26T12:25:28.837Z | user\n\nИсправлен fallback-путь: по умолчанию ищет state.json в internet-radio-music-db, а не в music-db. Поддержка старого имени как альтернативы.\n\nv1.5.0 | 2026-05-26T12:08:08.277Z | user\n\nАвтоопределение пути к базе: скрипты ищут state.json в папке music-db автоматически. Поддержка переменной MUSIC_DB_PATH для кастомного пути.\n\nv1.4.0 | 2026-05-26T11:56:37.756Z | user\n\nПути к базе и состоянию теперь через переменные окружения MUSIC_DB_PATH и MUSIC_PLAYER_STATE_PATH для совместимости с установкой через ClawHub\n\nv1.3.0 | 2026-05-26T11:37:40.582Z | user\n\nОбновлена версия для консистентности\n\nv1.2.0 | 2026-05-26T11:20:33.879Z | user\n\nПереименован: Music Player (Foobar2000) -> Internet Radio Music Player\n\nArchive index:\n\nArchive v2.5.3: 6 files, 16453 bytes\n\nFiles: _meta.json (146b), scripts/play_music.py (21152b), scripts/show_history.py (11760b), skill-card.md (2183b), SKILL.md (10054b), state.json (6362b)\n\nFile v2.5.3:SKILL.md\n\n---\nname: internet-radio-music-player\nversion: 2.5.0\ndescription: Internet radio stream player via Foobar2000. Smart 4-level relevance sorting by genre. Supports: play/stop/next/prev/resume, playback history with filters and export. Requires the Internet Radio Music DB skill. For the easiest management experience, use the internet-radio-music-webui plugin.\nsummary: Internet radio stream player via Foobar2000. Plays music by mood, selecting genre and stream from the Internet Radio Music DB with playback controls and history. Use the internet-radio-music-webui plugin for the simplest playback and DB management.\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n    emoji: \"🎶\"\n    homepage: https://clawhub.ai/skills/internet-radio-music-player\n---\n\n# Internet Radio Music Player\n\n**⚠️ WARNING: This skill REQUIRES the Internet Radio Music DB skill to work!**\n\nWithout the stream database skill installed, playback is impossible.\n\n## 🌐 WebUI Plugin (Recommended)\n\n**The easiest way to manage playback and the stream database is the [internet-radio-music-webui](https://clawhub.ai/dynamicsAlex/internet-radio-music-webui) plugin.**\n\nThe plugin provides an embeddable web panel with:\n- **Playback controls**: Play, Stop, Next, Previous, Resume (auto-resume after stop)\n- **Mood-based genre selector**: Pick from 20+ genres via dropdown\n- **Stream database management**: View stats (genres, languages, efficiency), list streams, check availability, rebuild database — all from the browser\n- **WebChat integration**: Embed directly in webchat with `[embed url=\"http://127.0.0.1:18789/mplayer\"]`\n\n**Install the plugin:**\n```bash\nopenclaw plugins install \"clawhub:internet-radio-music-webui\"\nopenclaw gateway restart\n```\n\nThe plugin auto-detects `play_music.py` and the database scripts from this skill and the Internet Radio Music DB skill.\n\n## Install dependencies\n\n```bash\n# 1. Install the stream database skill (required!)\nopenclaw skills install internet-radio-music-db\n\n# 2. Restart Gateway\nopenclaw gateway restart\n```\n\n## How it works\n\n1. User specifies a mood (e.g. \"play happy music\")\n2. Skill determines suitable genres from the mood map\n3. **Streams are fetched from the Internet Radio Music DB** (`~/.openclaw/skills/internet-radio-music-db/state.json`)\n4. Streams are sorted by relevance to the requested genre (see algorithm below)\n5. Stream availability is checked (HTTP request)\n6. Foobar2000 is launched with the found URL\n7. History is saved to `state.json`\n\n## Stream selection algorithm\n\nWhen selecting a stream from the database, a 4-level relevance sorting is applied:\n\n### 1. Primary `genre` match (highest priority)\n\nStreams with an exact `genre` match (database field) are always ranked higher than those matched only via the `genres` list.\n\n### 2. Genre position in `genres` field\n\nThe requested genre is searched in the stream's `genres` list. The **closer to the beginning** — the higher the priority. If `genre` matches exactly and `genres` is empty — position=0 (ideal).\n\nExample: requested `ambient`\n- `genre=ambient, genres=[]` → level=0, position=0 ✅\n- `genre=chill, genres=[\"Ambient\", \"Chill\", \"Downtempo\"]` → level=1, position=0\n- `genre=rock, genres=[\"Downtempo\", \"Chill\", \"Ambient\"]` → level=1, position=2\n\n### 3. Number of \"extra\" genres\n\nGiven equal level and position — the stream with **fewer subgenres** wins.\n\n### 4. Stream speed\n\nAll other things being equal — the **faster** stream is chosen.\n\n### Final sort key\n\n```\n(genre_match_level, position, extra_genres, -speed)\n```\n\nLower value = more relevant stream.\n\n### `next` command\n\nSwitches to the next stream **of the same genre** from the database (using relevance sorting). Does not switch to a history entry.\n\n## Mood → Genres\n\n| Mood (keywords) | Genres from DB |\n|-----------------|----------------|\n| calm, sleep, rest, background, meditation | ambient, classical, folk |\n| happy, fun, dance, energy | dance, disco, pop, funk, house |\n| sad, blues, melancholy | blues, jazz, soul, ambient |\n| rock, hard, garage | rock, metal, punk, alternative, indie |\n| electronic, synth, lo-fi, dream | electronic, ambient, house, techno |\n| classical, orchestra, symphony | classical |\n| reggae, tropical, summer | reggae, latin, disco |\n| hip-hop, rap, R&B, soul | soul, funk, pop, disco |\n| techno, rave, club, trance | techno, house, trance, electronic, dance |\n| jazz, swing | jazz, blues, soul |\n| country, western, folk | country, folk |\n| lounge, chill-out | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| metal, heavy, power, aggression | metal, punk, rock |\n| 80s, 90s, retro, nostalgia | 80s, 90s, oldies, disco, pop |\n| indie, alternative, experimental | indie, alternative |\n| latin, salsa, bachata, brazil | latin |\n| pop, popular, hits | pop, top-40 |\n| work, focus, study | ambient, classical, electronic |\n| party, dancefloor | dance, house, techno, pop, funk, disco |\n| sunset, chill, evening, lounge | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| news, talk, podcast | news, talk |\n| gospel, church, spiritual | gospel, classical, ambient |\n\n## Commands\n\n| Command | Action |\n|---------|--------|\n| **\"Play music\"** | Play ambient (by default) |\n| **\"Play [mood] music\"** | Determine genre and play |\n| **\"Play jazz\" / \"Play sad music\"** | Jazz / blues |\n| **\"Play happy music\"** | Dance / disco / pop |\n| **\"Play music for sleeping\"** | Ambient / classical |\n| **\"Play rock\" / \"Play heavy music\"** | Rock / metal |\n| **\"Play electronic music\"** | Electronic / techno |\n| **\"Play reggae\" / \"Play summer music\"** | Reggae / latin |\n| **\"Play classical\"** | Classical |\n| **\"Play 80s music\"** | 80s |\n| **\"Next\" / \"Other stream\"** | Next stream of same genre |\n| **\"Previous\" / \"Back\"** | Return to previous stream |\n| **\"Play what was playing\" / \"Last stream\"** | Play the most recent stream from all history |\n| **\"Stop\"** | Stop playback |\n| **\"What's playing?\" / \"Status\"** | Show current stream |\n| **\"History\" / \"Playback list\"** | Show history |\n\n## Stream source\n\n**Music Stream Database** (`~/.openclaw/skills/internet-radio-music-db/`):\n- ~1000+ streams from 29 genres\n- Auto-populated every 3 hours from internet-radio.com\n- 29 genres collected in parallel\n- Streams are speed-checked during population (60 workers, 4 sec)\n- Streams with `failed_checks >= 3` are automatically removed from the database\n\n## Files\n\n| File | Purpose |\n|------|---------|\n| `scripts/play_music.py` | Main playback script (play/stop/next/prev/resume/status/history) |\n| `scripts/show_history.py` | Detailed playback history with filters and export (CSV/HTML/JSON) |\n| `state.json` | Current genre, playback history, current stream |\n| `~/.openclaw/skills/internet-radio-music-db/state.json` | Stream database (managed by Internet Radio Music DB skill) |\n\n## Dependencies\n\n- **Python 3** — for playback scripts\n- **Foobar2000** — music player (auto-detects path: `C:\\Program Files\\foobar2000\\` or `C:\\Program Files (x86)\\foobar2000\\`)\n- **Internet Radio Music DB** — stream database skill (required!)\n\n## Changelog\n\n### v2.5.0 (2026-05-29)\n\n- Added information about the **internet-radio-music-webui** plugin — the easiest way to manage playback and stream database\n- Plugin provides web panel with playback controls, mood-based genre selector, and DB management (stats, list, check, rebuild)\n- Both internet-radio-music-db skill and this skill are required for the plugin to work\n\n### v2.4.0 (2026-05-29)\n\n- **Smart `play` after `stop` — auto-resume:** if playback was stopped via `stop`, pressing `play` without specifying a mood/genre resumes the last played stream from history instead of starting a new random one. State tracks `Stopped` flag to distinguish between \"never played\" and \"explicitly stopped\".\n- **Changed `--mood` default** from `\"ambient\"` to `None` — allows detecting when no genre was explicitly requested by the user. Internal fallback to `\"ambient\"` still applies when playing a new stream.\n- Updated `cmd_play` signature: entered genre always resets `Stopped` flag, ensuring explicit genre requests always start fresh.\n\n### v2.3.0 (2026-05-27)\n\n- **Removed `random.shuffle`** — previously, streams were shuffled after relevance sorting, causing multi-genre streams with a different primary genre (e.g. dance) to play instead of pure genre matches (e.g. country). Now the relevance order is always respected: pure genres first, multi-genre second.\n- Updated documentation with bug description and fix details\n- Full English translation of SKILL.md\n\n### v2.2.0 (2026-05-27)\n\n- **Improved stream sorting — now 4 priority levels:**\n  1. Primary `genre` match (exact > only in `genres` > none)\n  2. Requested genre position in `genres` field (closer to start = better)\n  3. Number of extra subgenres (fewer = more precise)\n  4. Stream speed (faster = better)\n- **Fixed `next` command** — now selects a stream from the database by current stream's genre (instead of random history switching). Uses the same relevance logic as `play`\n- **Fixed Foobar2000 switching** — now uses correct `stop` → `play` within the running player instead of `taskkill + restart`\n- **Handled empty `genres`** — if `genre` matches exactly and `genres` is empty, stream gets position=0 (ideal match)\n- **Discovered and documented database bug** — the same stream could exist dozens of times with different `genre/genres`, breaking sort order\n\n### v2.1.0 (2026-05-27)\n\n- **Smart stream relevance sorting** — 3-level selection system:\n  1. Requested genre position in `genres` field\n  2. Number of extra subgenres\n  3. Stream speed\n- **Foobar2000 path auto-detection** — automatically finds installation in `Program Files` and `Program Files (x86)`\n- **Added `lounge` genre** to mood map (chill/sunset/evening pattern)\n- **Added Russian word \"кантри\"** to mood map\n- **Support for `genres` as string** — parsing via comma and semicolon\n- Updated documentation with stream selection algorithm description\n\n### v2.0.0\n\n- Initial release\n\nFile v2.5.3:_meta.json\n\n{\n  \"ownerId\": \"kn775k2zzav7y8rpwwm218x0b587f0hj\",\n  \"slug\": \"internet-radio-music-player\",\n  \"version\": \"2.5.3\",\n  \"publishedAt\": 1780660206082\n}\n\nFile v2.5.3:skill-card.md\n\n## Description:\n\nPlays internet radio streams via Foobar2000 by mapping mood or genre requests to stations from the Internet Radio Music DB, with playback controls and history support.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[dynamicsalex](https://clawhub.ai/user/dynamicsalex)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to control internet radio playback from an agent, including mood-based station selection, playback controls, status checks, and listening history review.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill opens external stream URLs and performs outbound stream checks.\n\nMitigation: Install only in environments where outbound radio stream access is acceptable, and prefer explicit radio-specific requests to reduce accidental activation.\n\nRisk: The skill can control and force-stop local Foobar2000 processes.\n\nMitigation: Use it on systems where agent-driven Foobar2000 control is expected, and avoid running it during unrelated manual Foobar2000 sessions.\n\nRisk: Playback history exports can include stream metadata in HTML or CSV formats.\n\nMitigation: Sanitize exported history before opening files that contain untrusted stream metadata.\n\n## Reference(s):\n\n- [ClawHub Skill Page](https://clawhub.ai/dynamicsalex/skills/internet-radio-music-player)\n- [Internet Radio Music WebUI Plugin](https://clawhub.ai/dynamicsAlex/internet-radio-music-webui)\n\n## Skill Output:\n\n**Output Type(s):** [text, shell commands, configuration, files]\n\n**Output Format:** [Plain text command output with optional CSV, HTML, or JSON history exports.]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Requires Python 3, Foobar2000, and the Internet Radio Music DB skill.]\n\n## Skill Version(s):\n\n2.5.3 (source: server release evidence; artifact frontmatter says 2.5.0)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v2.5.3:state.json\n\n{\r\n  \"History\": [\r\n    {\r\n      \"Time\": \"2026-05-28 20:23:11\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"01:25:03\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-28 21:48:17\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Spirit Country Radio\",\r\n      \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n      \"Duration\": \"00:44:06\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-28 22:43:31\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 09:14:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Spirit Country Radio\",\r\n      \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n      \"Duration\": \"00:04:16\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 09:18:43\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"01:27:13\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 10:45:59\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"All Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8024/stream\",\r\n      \"Duration\": \"00:19:22\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:05:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"00:36:58\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:36\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:03\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:43\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:50\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:19\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:12\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:10\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:25\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:10\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:38\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:08\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:49\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:45:09\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"00:00:12\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:45:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"All Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8024/stream\",\r\n      \"Duration\": \"00:00:20\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:46:19\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:12\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:22\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:04\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:29\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:36\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:43\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:05\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:51\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:12\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:14:06\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:06\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:28:44\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:19:22\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:48:09\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:03:14\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:51:39\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:07\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:51:52\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:05\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:52:37\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:26:53\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 13:19:48\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"01:33:08\"\r\n    }\r\n  ],\r\n  \"CurrentGenre\": \"ambient\",\r\n  \"CurrentIndex\": 0,\r\n  \"Volume\": 50,\r\n  \"CurrentStream\": null,\r\n  \"Stopped\": true\r\n}\n\nArchive v2.5.2: 6 files, 16471 bytes\n\nFiles: _meta.json (146b), scripts/play_music.py (21152b), scripts/show_history.py (11760b), skill-card.md (2393b), SKILL.md (10054b), state.json (6362b)\n\nFile v2.5.2:SKILL.md\n\n---\nname: internet-radio-music-player\nversion: 2.5.0\ndescription: Internet radio stream player via Foobar2000. Smart 4-level relevance sorting by genre. Supports: play/stop/next/prev/resume, playback history with filters and export. Requires the Internet Radio Music DB skill. For the easiest management experience, use the internet-radio-music-webui plugin.\nsummary: Internet radio stream player via Foobar2000. Plays music by mood, selecting genre and stream from the Internet Radio Music DB with playback controls and history. Use the internet-radio-music-webui plugin for the simplest playback and DB management.\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n    emoji: \"🎶\"\n    homepage: https://clawhub.ai/skills/internet-radio-music-player\n---\n\n# Internet Radio Music Player\n\n**⚠️ WARNING: This skill REQUIRES the Internet Radio Music DB skill to work!**\n\nWithout the stream database skill installed, playback is impossible.\n\n## 🌐 WebUI Plugin (Recommended)\n\n**The easiest way to manage playback and the stream database is the [internet-radio-music-webui](https://clawhub.ai/dynamicsAlex/internet-radio-music-webui) plugin.**\n\nThe plugin provides an embeddable web panel with:\n- **Playback controls**: Play, Stop, Next, Previous, Resume (auto-resume after stop)\n- **Mood-based genre selector**: Pick from 20+ genres via dropdown\n- **Stream database management**: View stats (genres, languages, efficiency), list streams, check availability, rebuild database — all from the browser\n- **WebChat integration**: Embed directly in webchat with `[embed url=\"http://127.0.0.1:18789/mplayer\"]`\n\n**Install the plugin:**\n```bash\nopenclaw plugins install \"clawhub:internet-radio-music-webui\"\nopenclaw gateway restart\n```\n\nThe plugin auto-detects `play_music.py` and the database scripts from this skill and the Internet Radio Music DB skill.\n\n## Install dependencies\n\n```bash\n# 1. Install the stream database skill (required!)\nopenclaw skills install internet-radio-music-db\n\n# 2. Restart Gateway\nopenclaw gateway restart\n```\n\n## How it works\n\n1. User specifies a mood (e.g. \"play happy music\")\n2. Skill determines suitable genres from the mood map\n3. **Streams are fetched from the Internet Radio Music DB** (`~/.openclaw/skills/internet-radio-music-db/state.json`)\n4. Streams are sorted by relevance to the requested genre (see algorithm below)\n5. Stream availability is checked (HTTP request)\n6. Foobar2000 is launched with the found URL\n7. History is saved to `state.json`\n\n## Stream selection algorithm\n\nWhen selecting a stream from the database, a 4-level relevance sorting is applied:\n\n### 1. Primary `genre` match (highest priority)\n\nStreams with an exact `genre` match (database field) are always ranked higher than those matched only via the `genres` list.\n\n### 2. Genre position in `genres` field\n\nThe requested genre is searched in the stream's `genres` list. The **closer to the beginning** — the higher the priority. If `genre` matches exactly and `genres` is empty — position=0 (ideal).\n\nExample: requested `ambient`\n- `genre=ambient, genres=[]` → level=0, position=0 ✅\n- `genre=chill, genres=[\"Ambient\", \"Chill\", \"Downtempo\"]` → level=1, position=0\n- `genre=rock, genres=[\"Downtempo\", \"Chill\", \"Ambient\"]` → level=1, position=2\n\n### 3. Number of \"extra\" genres\n\nGiven equal level and position — the stream with **fewer subgenres** wins.\n\n### 4. Stream speed\n\nAll other things being equal — the **faster** stream is chosen.\n\n### Final sort key\n\n```\n(genre_match_level, position, extra_genres, -speed)\n```\n\nLower value = more relevant stream.\n\n### `next` command\n\nSwitches to the next stream **of the same genre** from the database (using relevance sorting). Does not switch to a history entry.\n\n## Mood → Genres\n\n| Mood (keywords) | Genres from DB |\n|-----------------|----------------|\n| calm, sleep, rest, background, meditation | ambient, classical, folk |\n| happy, fun, dance, energy | dance, disco, pop, funk, house |\n| sad, blues, melancholy | blues, jazz, soul, ambient |\n| rock, hard, garage | rock, metal, punk, alternative, indie |\n| electronic, synth, lo-fi, dream | electronic, ambient, house, techno |\n| classical, orchestra, symphony | classical |\n| reggae, tropical, summer | reggae, latin, disco |\n| hip-hop, rap, R&B, soul | soul, funk, pop, disco |\n| techno, rave, club, trance | techno, house, trance, electronic, dance |\n| jazz, swing | jazz, blues, soul |\n| country, western, folk | country, folk |\n| lounge, chill-out | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| metal, heavy, power, aggression | metal, punk, rock |\n| 80s, 90s, retro, nostalgia | 80s, 90s, oldies, disco, pop |\n| indie, alternative, experimental | indie, alternative |\n| latin, salsa, bachata, brazil | latin |\n| pop, popular, hits | pop, top-40 |\n| work, focus, study | ambient, classical, electronic |\n| party, dancefloor | dance, house, techno, pop, funk, disco |\n| sunset, chill, evening, lounge | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| news, talk, podcast | news, talk |\n| gospel, church, spiritual | gospel, classical, ambient |\n\n## Commands\n\n| Command | Action |\n|---------|--------|\n| **\"Play music\"** | Play ambient (by default) |\n| **\"Play [mood] music\"** | Determine genre and play |\n| **\"Play jazz\" / \"Play sad music\"** | Jazz / blues |\n| **\"Play happy music\"** | Dance / disco / pop |\n| **\"Play music for sleeping\"** | Ambient / classical |\n| **\"Play rock\" / \"Play heavy music\"** | Rock / metal |\n| **\"Play electronic music\"** | Electronic / techno |\n| **\"Play reggae\" / \"Play summer music\"** | Reggae / latin |\n| **\"Play classical\"** | Classical |\n| **\"Play 80s music\"** | 80s |\n| **\"Next\" / \"Other stream\"** | Next stream of same genre |\n| **\"Previous\" / \"Back\"** | Return to previous stream |\n| **\"Play what was playing\" / \"Last stream\"** | Play the most recent stream from all history |\n| **\"Stop\"** | Stop playback |\n| **\"What's playing?\" / \"Status\"** | Show current stream |\n| **\"History\" / \"Playback list\"** | Show history |\n\n## Stream source\n\n**Music Stream Database** (`~/.openclaw/skills/internet-radio-music-db/`):\n- ~1000+ streams from 29 genres\n- Auto-populated every 3 hours from internet-radio.com\n- 29 genres collected in parallel\n- Streams are speed-checked during population (60 workers, 4 sec)\n- Streams with `failed_checks >= 3` are automatically removed from the database\n\n## Files\n\n| File | Purpose |\n|------|---------|\n| `scripts/play_music.py` | Main playback script (play/stop/next/prev/resume/status/history) |\n| `scripts/show_history.py` | Detailed playback history with filters and export (CSV/HTML/JSON) |\n| `state.json` | Current genre, playback history, current stream |\n| `~/.openclaw/skills/internet-radio-music-db/state.json` | Stream database (managed by Internet Radio Music DB skill) |\n\n## Dependencies\n\n- **Python 3** — for playback scripts\n- **Foobar2000** — music player (auto-detects path: `C:\\Program Files\\foobar2000\\` or `C:\\Program Files (x86)\\foobar2000\\`)\n- **Internet Radio Music DB** — stream database skill (required!)\n\n## Changelog\n\n### v2.5.0 (2026-05-29)\n\n- Added information about the **internet-radio-music-webui** plugin — the easiest way to manage playback and stream database\n- Plugin provides web panel with playback controls, mood-based genre selector, and DB management (stats, list, check, rebuild)\n- Both internet-radio-music-db skill and this skill are required for the plugin to work\n\n### v2.4.0 (2026-05-29)\n\n- **Smart `play` after `stop` — auto-resume:** if playback was stopped via `stop`, pressing `play` without specifying a mood/genre resumes the last played stream from history instead of starting a new random one. State tracks `Stopped` flag to distinguish between \"never played\" and \"explicitly stopped\".\n- **Changed `--mood` default** from `\"ambient\"` to `None` — allows detecting when no genre was explicitly requested by the user. Internal fallback to `\"ambient\"` still applies when playing a new stream.\n- Updated `cmd_play` signature: entered genre always resets `Stopped` flag, ensuring explicit genre requests always start fresh.\n\n### v2.3.0 (2026-05-27)\n\n- **Removed `random.shuffle`** — previously, streams were shuffled after relevance sorting, causing multi-genre streams with a different primary genre (e.g. dance) to play instead of pure genre matches (e.g. country). Now the relevance order is always respected: pure genres first, multi-genre second.\n- Updated documentation with bug description and fix details\n- Full English translation of SKILL.md\n\n### v2.2.0 (2026-05-27)\n\n- **Improved stream sorting — now 4 priority levels:**\n  1. Primary `genre` match (exact > only in `genres` > none)\n  2. Requested genre position in `genres` field (closer to start = better)\n  3. Number of extra subgenres (fewer = more precise)\n  4. Stream speed (faster = better)\n- **Fixed `next` command** — now selects a stream from the database by current stream's genre (instead of random history switching). Uses the same relevance logic as `play`\n- **Fixed Foobar2000 switching** — now uses correct `stop` → `play` within the running player instead of `taskkill + restart`\n- **Handled empty `genres`** — if `genre` matches exactly and `genres` is empty, stream gets position=0 (ideal match)\n- **Discovered and documented database bug** — the same stream could exist dozens of times with different `genre/genres`, breaking sort order\n\n### v2.1.0 (2026-05-27)\n\n- **Smart stream relevance sorting** — 3-level selection system:\n  1. Requested genre position in `genres` field\n  2. Number of extra subgenres\n  3. Stream speed\n- **Foobar2000 path auto-detection** — automatically finds installation in `Program Files` and `Program Files (x86)`\n- **Added `lounge` genre** to mood map (chill/sunset/evening pattern)\n- **Added Russian word \"кантри\"** to mood map\n- **Support for `genres` as string** — parsing via comma and semicolon\n- Updated documentation with stream selection algorithm description\n\n### v2.0.0\n\n- Initial release\n\nFile v2.5.2:_meta.json\n\n{\n  \"ownerId\": \"kn775k2zzav7y8rpwwm218x0b587f0hj\",\n  \"slug\": \"internet-radio-music-player\",\n  \"version\": \"2.5.2\",\n  \"publishedAt\": 1780657424817\n}\n\nFile v2.5.2:skill-card.md\n\n## Description: <br>\nPlays internet radio streams via Foobar2000 based on mood, selecting a genre and stream from the Internet Radio Music DB with playback controls and history support. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[dynamicsalex](https://clawhub.ai/user/dynamicsalex) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users and developers use this skill to ask an agent to play mood- or genre-based internet radio through Foobar2000, control playback, and inspect or export playback history. It is intended for environments where the required Internet Radio Music DB skill and Foobar2000 are available. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill opens outbound connections to internet radio streams and can play a user-supplied stream URL. <br>\nMitigation: Use explicit genre commands or trusted stream URLs, and avoid passing untrusted URLs to playurl. <br>\nRisk: The skill stores local playback state and history in state.json. <br>\nMitigation: Review or clear playback history when stream choices are sensitive, and use it only in environments where local history storage is acceptable. <br>\nRisk: The skill controls local Foobar2000 playback. <br>\nMitigation: Install and use it only on systems where agent-controlled local audio playback is expected. <br>\n\n\n## Reference(s): <br>\n- [ClawHub release page](https://clawhub.ai/dynamicsalex/internet-radio-music-player) <br>\n- [Internet Radio Music WebUI plugin](https://clawhub.ai/dynamicsAlex/internet-radio-music-webui) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance] <br>\n**Output Format:** [Markdown or plain text responses with shell command examples and playback, status, history, or export summaries.] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [May include playback commands, stream status, history filters, and export instructions.] <br>\n\n## Skill Version(s): <br>\n2.5.2 (source: server release metadata) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v2.5.2:state.json\n\n{\r\n  \"History\": [\r\n    {\r\n      \"Time\": \"2026-05-28 20:23:11\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"01:25:03\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-28 21:48:17\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Spirit Country Radio\",\r\n      \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n      \"Duration\": \"00:44:06\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-28 22:43:31\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 09:14:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Spirit Country Radio\",\r\n      \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n      \"Duration\": \"00:04:16\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 09:18:43\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"01:27:13\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 10:45:59\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"All Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8024/stream\",\r\n      \"Duration\": \"00:19:22\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:05:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"00:36:58\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:36\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:03\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:43\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:50\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:19\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:12\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:10\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:25\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:10\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:38\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:08\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:49\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:45:09\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"00:00:12\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:45:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"All Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8024/stream\",\r\n      \"Duration\": \"00:00:20\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:46:19\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:12\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:22\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:04\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:29\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:36\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:43\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:05\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:51\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:12\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:14:06\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:06\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:28:44\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:19:22\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:48:09\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:03:14\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:51:39\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:07\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:51:52\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:05\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:52:37\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:26:53\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 13:19:48\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"01:33:08\"\r\n    }\r\n  ],\r\n  \"CurrentGenre\": \"ambient\",\r\n  \"CurrentIndex\": 0,\r\n  \"Volume\": 50,\r\n  \"CurrentStream\": null,\r\n  \"Stopped\": true\r\n}\n\nArchive v2.5.1: 6 files, 16465 bytes\n\nFiles: _meta.json (146b), scripts/play_music.py (21152b), scripts/show_history.py (11760b), skill-card.md (2426b), SKILL.md (10054b), state.json (6362b)\n\nFile v2.5.1:SKILL.md\n\n---\nname: internet-radio-music-player\nversion: 2.5.0\ndescription: Internet radio stream player via Foobar2000. Smart 4-level relevance sorting by genre. Supports: play/stop/next/prev/resume, playback history with filters and export. Requires the Internet Radio Music DB skill. For the easiest management experience, use the internet-radio-music-webui plugin.\nsummary: Internet radio stream player via Foobar2000. Plays music by mood, selecting genre and stream from the Internet Radio Music DB with playback controls and history. Use the internet-radio-music-webui plugin for the simplest playback and DB management.\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n    emoji: \"🎶\"\n    homepage: https://clawhub.ai/skills/internet-radio-music-player\n---\n\n# Internet Radio Music Player\n\n**⚠️ WARNING: This skill REQUIRES the Internet Radio Music DB skill to work!**\n\nWithout the stream database skill installed, playback is impossible.\n\n## 🌐 WebUI Plugin (Recommended)\n\n**The easiest way to manage playback and the stream database is the [internet-radio-music-webui](https://clawhub.ai/dynamicsAlex/internet-radio-music-webui) plugin.**\n\nThe plugin provides an embeddable web panel with:\n- **Playback controls**: Play, Stop, Next, Previous, Resume (auto-resume after stop)\n- **Mood-based genre selector**: Pick from 20+ genres via dropdown\n- **Stream database management**: View stats (genres, languages, efficiency), list streams, check availability, rebuild database — all from the browser\n- **WebChat integration**: Embed directly in webchat with `[embed url=\"http://127.0.0.1:18789/mplayer\"]`\n\n**Install the plugin:**\n```bash\nopenclaw plugins install \"clawhub:internet-radio-music-webui\"\nopenclaw gateway restart\n```\n\nThe plugin auto-detects `play_music.py` and the database scripts from this skill and the Internet Radio Music DB skill.\n\n## Install dependencies\n\n```bash\n# 1. Install the stream database skill (required!)\nopenclaw skills install internet-radio-music-db\n\n# 2. Restart Gateway\nopenclaw gateway restart\n```\n\n## How it works\n\n1. User specifies a mood (e.g. \"play happy music\")\n2. Skill determines suitable genres from the mood map\n3. **Streams are fetched from the Internet Radio Music DB** (`~/.openclaw/skills/internet-radio-music-db/state.json`)\n4. Streams are sorted by relevance to the requested genre (see algorithm below)\n5. Stream availability is checked (HTTP request)\n6. Foobar2000 is launched with the found URL\n7. History is saved to `state.json`\n\n## Stream selection algorithm\n\nWhen selecting a stream from the database, a 4-level relevance sorting is applied:\n\n### 1. Primary `genre` match (highest priority)\n\nStreams with an exact `genre` match (database field) are always ranked higher than those matched only via the `genres` list.\n\n### 2. Genre position in `genres` field\n\nThe requested genre is searched in the stream's `genres` list. The **closer to the beginning** — the higher the priority. If `genre` matches exactly and `genres` is empty — position=0 (ideal).\n\nExample: requested `ambient`\n- `genre=ambient, genres=[]` → level=0, position=0 ✅\n- `genre=chill, genres=[\"Ambient\", \"Chill\", \"Downtempo\"]` → level=1, position=0\n- `genre=rock, genres=[\"Downtempo\", \"Chill\", \"Ambient\"]` → level=1, position=2\n\n### 3. Number of \"extra\" genres\n\nGiven equal level and position — the stream with **fewer subgenres** wins.\n\n### 4. Stream speed\n\nAll other things being equal — the **faster** stream is chosen.\n\n### Final sort key\n\n```\n(genre_match_level, position, extra_genres, -speed)\n```\n\nLower value = more relevant stream.\n\n### `next` command\n\nSwitches to the next stream **of the same genre** from the database (using relevance sorting). Does not switch to a history entry.\n\n## Mood → Genres\n\n| Mood (keywords) | Genres from DB |\n|-----------------|----------------|\n| calm, sleep, rest, background, meditation | ambient, classical, folk |\n| happy, fun, dance, energy | dance, disco, pop, funk, house |\n| sad, blues, melancholy | blues, jazz, soul, ambient |\n| rock, hard, garage | rock, metal, punk, alternative, indie |\n| electronic, synth, lo-fi, dream | electronic, ambient, house, techno |\n| classical, orchestra, symphony | classical |\n| reggae, tropical, summer | reggae, latin, disco |\n| hip-hop, rap, R&B, soul | soul, funk, pop, disco |\n| techno, rave, club, trance | techno, house, trance, electronic, dance |\n| jazz, swing | jazz, blues, soul |\n| country, western, folk | country, folk |\n| lounge, chill-out | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| metal, heavy, power, aggression | metal, punk, rock |\n| 80s, 90s, retro, nostalgia | 80s, 90s, oldies, disco, pop |\n| indie, alternative, experimental | indie, alternative |\n| latin, salsa, bachata, brazil | latin |\n| pop, popular, hits | pop, top-40 |\n| work, focus, study | ambient, classical, electronic |\n| party, dancefloor | dance, house, techno, pop, funk, disco |\n| sunset, chill, evening, lounge | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| news, talk, podcast | news, talk |\n| gospel, church, spiritual | gospel, classical, ambient |\n\n## Commands\n\n| Command | Action |\n|---------|--------|\n| **\"Play music\"** | Play ambient (by default) |\n| **\"Play [mood] music\"** | Determine genre and play |\n| **\"Play jazz\" / \"Play sad music\"** | Jazz / blues |\n| **\"Play happy music\"** | Dance / disco / pop |\n| **\"Play music for sleeping\"** | Ambient / classical |\n| **\"Play rock\" / \"Play heavy music\"** | Rock / metal |\n| **\"Play electronic music\"** | Electronic / techno |\n| **\"Play reggae\" / \"Play summer music\"** | Reggae / latin |\n| **\"Play classical\"** | Classical |\n| **\"Play 80s music\"** | 80s |\n| **\"Next\" / \"Other stream\"** | Next stream of same genre |\n| **\"Previous\" / \"Back\"** | Return to previous stream |\n| **\"Play what was playing\" / \"Last stream\"** | Play the most recent stream from all history |\n| **\"Stop\"** | Stop playback |\n| **\"What's playing?\" / \"Status\"** | Show current stream |\n| **\"History\" / \"Playback list\"** | Show history |\n\n## Stream source\n\n**Music Stream Database** (`~/.openclaw/skills/internet-radio-music-db/`):\n- ~1000+ streams from 29 genres\n- Auto-populated every 3 hours from internet-radio.com\n- 29 genres collected in parallel\n- Streams are speed-checked during population (60 workers, 4 sec)\n- Streams with `failed_checks >= 3` are automatically removed from the database\n\n## Files\n\n| File | Purpose |\n|------|---------|\n| `scripts/play_music.py` | Main playback script (play/stop/next/prev/resume/status/history) |\n| `scripts/show_history.py` | Detailed playback history with filters and export (CSV/HTML/JSON) |\n| `state.json` | Current genre, playback history, current stream |\n| `~/.openclaw/skills/internet-radio-music-db/state.json` | Stream database (managed by Internet Radio Music DB skill) |\n\n## Dependencies\n\n- **Python 3** — for playback scripts\n- **Foobar2000** — music player (auto-detects path: `C:\\Program Files\\foobar2000\\` or `C:\\Program Files (x86)\\foobar2000\\`)\n- **Internet Radio Music DB** — stream database skill (required!)\n\n## Changelog\n\n### v2.5.0 (2026-05-29)\n\n- Added information about the **internet-radio-music-webui** plugin — the easiest way to manage playback and stream database\n- Plugin provides web panel with playback controls, mood-based genre selector, and DB management (stats, list, check, rebuild)\n- Both internet-radio-music-db skill and this skill are required for the plugin to work\n\n### v2.4.0 (2026-05-29)\n\n- **Smart `play` after `stop` — auto-resume:** if playback was stopped via `stop`, pressing `play` without specifying a mood/genre resumes the last played stream from history instead of starting a new random one. State tracks `Stopped` flag to distinguish between \"never played\" and \"explicitly stopped\".\n- **Changed `--mood` default** from `\"ambient\"` to `None` — allows detecting when no genre was explicitly requested by the user. Internal fallback to `\"ambient\"` still applies when playing a new stream.\n- Updated `cmd_play` signature: entered genre always resets `Stopped` flag, ensuring explicit genre requests always start fresh.\n\n### v2.3.0 (2026-05-27)\n\n- **Removed `random.shuffle`** — previously, streams were shuffled after relevance sorting, causing multi-genre streams with a different primary genre (e.g. dance) to play instead of pure genre matches (e.g. country). Now the relevance order is always respected: pure genres first, multi-genre second.\n- Updated documentation with bug description and fix details\n- Full English translation of SKILL.md\n\n### v2.2.0 (2026-05-27)\n\n- **Improved stream sorting — now 4 priority levels:**\n  1. Primary `genre` match (exact > only in `genres` > none)\n  2. Requested genre position in `genres` field (closer to start = better)\n  3. Number of extra subgenres (fewer = more precise)\n  4. Stream speed (faster = better)\n- **Fixed `next` command** — now selects a stream from the database by current stream's genre (instead of random history switching). Uses the same relevance logic as `play`\n- **Fixed Foobar2000 switching** — now uses correct `stop` → `play` within the running player instead of `taskkill + restart`\n- **Handled empty `genres`** — if `genre` matches exactly and `genres` is empty, stream gets position=0 (ideal match)\n- **Discovered and documented database bug** — the same stream could exist dozens of times with different `genre/genres`, breaking sort order\n\n### v2.1.0 (2026-05-27)\n\n- **Smart stream relevance sorting** — 3-level selection system:\n  1. Requested genre position in `genres` field\n  2. Number of extra subgenres\n  3. Stream speed\n- **Foobar2000 path auto-detection** — automatically finds installation in `Program Files` and `Program Files (x86)`\n- **Added `lounge` genre** to mood map (chill/sunset/evening pattern)\n- **Added Russian word \"кантри\"** to mood map\n- **Support for `genres` as string** — parsing via comma and semicolon\n- Updated documentation with stream selection algorithm description\n\n### v2.0.0\n\n- Initial release\n\nFile v2.5.1:_meta.json\n\n{\n  \"ownerId\": \"kn775k2zzav7y8rpwwm218x0b587f0hj\",\n  \"slug\": \"internet-radio-music-player\",\n  \"version\": \"2.5.1\",\n  \"publishedAt\": 1780054073975\n}\n\nFile v2.5.1:skill-card.md\n\n## Description: <br>\nInternet radio stream player via Foobar2000 with mood-based stream selection, playback controls, and local history export. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[dynamicsalex](https://clawhub.ai/user/dynamicsalex) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users and developers use this skill to play internet radio through Foobar2000 by mood or genre, move between streams, resume playback, and inspect or export listening history. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill opens internet radio URLs and performs outbound stream availability checks. <br>\nMitigation: Prefer streams from the companion Internet Radio Music DB and review any custom playurl target before use. <br>\nRisk: The skill controls the local Foobar2000 process, including stopping playback. <br>\nMitigation: Use it only on machines where local media-player control is expected and acceptable. <br>\nRisk: Playback history is stored locally and can be exported to CSV, HTML, or JSON. <br>\nMitigation: Review exported history files before sharing and remove entries that expose private listening activity or stream URLs. <br>\n\n\n## Reference(s): <br>\n- [Internet Radio Music Player on ClawHub](https://clawhub.ai/dynamicsalex/internet-radio-music-player) <br>\n- [Internet Radio Music Player skill homepage](https://clawhub.ai/skills/internet-radio-music-player) <br>\n- [Internet Radio Music WebUI companion plugin](https://clawhub.ai/dynamicsAlex/internet-radio-music-webui) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance] <br>\n**Output Format:** [Terminal text and Markdown guidance with optional CSV, HTML, or JSON history exports] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Controls local Foobar2000 playback, reads the companion Internet Radio Music DB state, and stores playback history locally.] <br>\n\n## Skill Version(s): <br>\n2.5.1 (source: server release metadata; artifact frontmatter states 2.5.0) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v2.5.1:state.json\n\n{\r\n  \"History\": [\r\n    {\r\n      \"Time\": \"2026-05-28 20:23:11\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"01:25:03\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-28 21:48:17\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Spirit Country Radio\",\r\n      \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n      \"Duration\": \"00:44:06\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-28 22:43:31\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 09:14:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Spirit Country Radio\",\r\n      \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n      \"Duration\": \"00:04:16\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 09:18:43\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"01:27:13\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 10:45:59\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"All Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8024/stream\",\r\n      \"Duration\": \"00:19:22\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:05:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"00:36:58\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:36\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:03\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:43\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:50\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:19\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:12\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:10\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:25\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:10\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:38\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:08\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:49\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:45:09\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"00:00:12\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:45:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"All Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8024/stream\",\r\n      \"Duration\": \"00:00:20\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:46:19\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:12\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:22\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:04\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:29\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:36\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:43\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:05\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:51\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:12\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:14:06\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:06\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:28:44\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:19:22\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:48:09\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:03:14\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:51:39\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:07\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:51:52\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:05\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:52:37\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:26:53\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 13:19:48\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"01:33:08\"\r\n    }\r\n  ],\r\n  \"CurrentGenre\": \"ambient\",\r\n  \"CurrentIndex\": 0,\r\n  \"Volume\": 50,\r\n  \"CurrentStream\": null,\r\n  \"Stopped\": true\r\n}\n\nArchive v2.5.0: 6 files, 16506 bytes\n\nFiles: _meta.json (146b), scripts/play_music.py (21152b), scripts/show_history.py (11760b), skill-card.md (2496b), SKILL.md (10044b), state.json (6362b)\n\nFile v2.5.0:SKILL.md\n\n---\nname: internet-radio-music-player\nversion: 2.5.0\ndescription: Internet radio stream player via Foobar2000. Smart 4-level relevance sorting by genre. Supports: play/stop/next/prev/resume, playback history with filters and export. Requires the Internet Radio Music DB skill. For the easiest management experience, use the internet-radio-music-webui plugin.\nsummary: Internet radio stream player via Foobar2000. Plays music by mood, selecting genre and stream from the Internet Radio Music DB with playback controls and history. Use the internet-radio-music-webui plugin for the simplest playback and DB management.\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n    emoji: \"🎶\"\n    homepage: https://clawhub.ai/skills/internet-radio-music-player\n---\n\n# Internet Radio Music Player\n\n**⚠️ WARNING: This skill REQUIRES the Internet Radio Music DB skill to work!**\n\nWithout the stream database skill installed, playback is impossible.\n\n## 🌐 WebUI Plugin (Recommended)\n\n**The easiest way to manage playback and the stream database is the [internet-radio-music-webui](https://clawhub.ai/dynamicsAlex/internet-radio-music-webui) plugin.**\n\nThe plugin provides an embeddable web panel with:\n- **Playback controls**: Play, Stop, Next, Previous, Resume (auto-resume after stop)\n- **Mood-based genre selector**: Pick from 20+ genres via dropdown\n- **Stream database management**: View stats (genres, languages, efficiency), list streams, check availability, rebuild database — all from the browser\n- **WebChat integration**: Embed directly in webchat with `[embed url=\"http://127.0.0.1:18789/mplayer\"]`\n\n**Install the plugin:**\n```bash\nopenclaw plugins install internet-radio-music-webui\nopenclaw gateway restart\n```\n\nThe plugin auto-detects `play_music.py` and the database scripts from this skill and the Internet Radio Music DB skill.\n\n## Install dependencies\n\n```bash\n# 1. Install the stream database skill (required!)\nopenclaw skills install internet-radio-music-db\n\n# 2. Restart Gateway\nopenclaw gateway restart\n```\n\n## How it works\n\n1. User specifies a mood (e.g. \"play happy music\")\n2. Skill determines suitable genres from the mood map\n3. **Streams are fetched from the Internet Radio Music DB** (`~/.openclaw/skills/internet-radio-music-db/state.json`)\n4. Streams are sorted by relevance to the requested genre (see algorithm below)\n5. Stream availability is checked (HTTP request)\n6. Foobar2000 is launched with the found URL\n7. History is saved to `state.json`\n\n## Stream selection algorithm\n\nWhen selecting a stream from the database, a 4-level relevance sorting is applied:\n\n### 1. Primary `genre` match (highest priority)\n\nStreams with an exact `genre` match (database field) are always ranked higher than those matched only via the `genres` list.\n\n### 2. Genre position in `genres` field\n\nThe requested genre is searched in the stream's `genres` list. The **closer to the beginning** — the higher the priority. If `genre` matches exactly and `genres` is empty — position=0 (ideal).\n\nExample: requested `ambient`\n- `genre=ambient, genres=[]` → level=0, position=0 ✅\n- `genre=chill, genres=[\"Ambient\", \"Chill\", \"Downtempo\"]` → level=1, position=0\n- `genre=rock, genres=[\"Downtempo\", \"Chill\", \"Ambient\"]` → level=1, position=2\n\n### 3. Number of \"extra\" genres\n\nGiven equal level and position — the stream with **fewer subgenres** wins.\n\n### 4. Stream speed\n\nAll other things being equal — the **faster** stream is chosen.\n\n### Final sort key\n\n```\n(genre_match_level, position, extra_genres, -speed)\n```\n\nLower value = more relevant stream.\n\n### `next` command\n\nSwitches to the next stream **of the same genre** from the database (using relevance sorting). Does not switch to a history entry.\n\n## Mood → Genres\n\n| Mood (keywords) | Genres from DB |\n|-----------------|----------------|\n| calm, sleep, rest, background, meditation | ambient, classical, folk |\n| happy, fun, dance, energy | dance, disco, pop, funk, house |\n| sad, blues, melancholy | blues, jazz, soul, ambient |\n| rock, hard, garage | rock, metal, punk, alternative, indie |\n| electronic, synth, lo-fi, dream | electronic, ambient, house, techno |\n| classical, orchestra, symphony | classical |\n| reggae, tropical, summer | reggae, latin, disco |\n| hip-hop, rap, R&B, soul | soul, funk, pop, disco |\n| techno, rave, club, trance | techno, house, trance, electronic, dance |\n| jazz, swing | jazz, blues, soul |\n| country, western, folk | country, folk |\n| lounge, chill-out | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| metal, heavy, power, aggression | metal, punk, rock |\n| 80s, 90s, retro, nostalgia | 80s, 90s, oldies, disco, pop |\n| indie, alternative, experimental | indie, alternative |\n| latin, salsa, bachata, brazil | latin |\n| pop, popular, hits | pop, top-40 |\n| work, focus, study | ambient, classical, electronic |\n| party, dancefloor | dance, house, techno, pop, funk, disco |\n| sunset, chill, evening, lounge | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| news, talk, podcast | news, talk |\n| gospel, church, spiritual | gospel, classical, ambient |\n\n## Commands\n\n| Command | Action |\n|---------|--------|\n| **\"Play music\"** | Play ambient (by default) |\n| **\"Play [mood] music\"** | Determine genre and play |\n| **\"Play jazz\" / \"Play sad music\"** | Jazz / blues |\n| **\"Play happy music\"** | Dance / disco / pop |\n| **\"Play music for sleeping\"** | Ambient / classical |\n| **\"Play rock\" / \"Play heavy music\"** | Rock / metal |\n| **\"Play electronic music\"** | Electronic / techno |\n| **\"Play reggae\" / \"Play summer music\"** | Reggae / latin |\n| **\"Play classical\"** | Classical |\n| **\"Play 80s music\"** | 80s |\n| **\"Next\" / \"Other stream\"** | Next stream of same genre |\n| **\"Previous\" / \"Back\"** | Return to previous stream |\n| **\"Play what was playing\" / \"Last stream\"** | Play the most recent stream from all history |\n| **\"Stop\"** | Stop playback |\n| **\"What's playing?\" / \"Status\"** | Show current stream |\n| **\"History\" / \"Playback list\"** | Show history |\n\n## Stream source\n\n**Music Stream Database** (`~/.openclaw/skills/internet-radio-music-db/`):\n- ~1000+ streams from 29 genres\n- Auto-populated every 3 hours from internet-radio.com\n- 29 genres collected in parallel\n- Streams are speed-checked during population (60 workers, 4 sec)\n- Streams with `failed_checks >= 3` are automatically removed from the database\n\n## Files\n\n| File | Purpose |\n|------|---------|\n| `scripts/play_music.py` | Main playback script (play/stop/next/prev/resume/status/history) |\n| `scripts/show_history.py` | Detailed playback history with filters and export (CSV/HTML/JSON) |\n| `state.json` | Current genre, playback history, current stream |\n| `~/.openclaw/skills/internet-radio-music-db/state.json` | Stream database (managed by Internet Radio Music DB skill) |\n\n## Dependencies\n\n- **Python 3** — for playback scripts\n- **Foobar2000** — music player (auto-detects path: `C:\\Program Files\\foobar2000\\` or `C:\\Program Files (x86)\\foobar2000\\`)\n- **Internet Radio Music DB** — stream database skill (required!)\n\n## Changelog\n\n### v2.5.0 (2026-05-29)\n\n- Added information about the **internet-radio-music-webui** plugin — the easiest way to manage playback and stream database\n- Plugin provides web panel with playback controls, mood-based genre selector, and DB management (stats, list, check, rebuild)\n- Both internet-radio-music-db skill and this skill are required for the plugin to work\n\n### v2.4.0 (2026-05-29)\n\n- **Smart `play` after `stop` — auto-resume:** if playback was stopped via `stop`, pressing `play` without specifying a mood/genre resumes the last played stream from history instead of starting a new random one. State tracks `Stopped` flag to distinguish between \"never played\" and \"explicitly stopped\".\n- **Changed `--mood` default** from `\"ambient\"` to `None` — allows detecting when no genre was explicitly requested by the user. Internal fallback to `\"ambient\"` still applies when playing a new stream.\n- Updated `cmd_play` signature: entered genre always resets `Stopped` flag, ensuring explicit genre requests always start fresh.\n\n### v2.3.0 (2026-05-27)\n\n- **Removed `random.shuffle`** — previously, streams were shuffled after relevance sorting, causing multi-genre streams with a different primary genre (e.g. dance) to play instead of pure genre matches (e.g. country). Now the relevance order is always respected: pure genres first, multi-genre second.\n- Updated documentation with bug description and fix details\n- Full English translation of SKILL.md\n\n### v2.2.0 (2026-05-27)\n\n- **Improved stream sorting — now 4 priority levels:**\n  1. Primary `genre` match (exact > only in `genres` > none)\n  2. Requested genre position in `genres` field (closer to start = better)\n  3. Number of extra subgenres (fewer = more precise)\n  4. Stream speed (faster = better)\n- **Fixed `next` command** — now selects a stream from the database by current stream's genre (instead of random history switching). Uses the same relevance logic as `play`\n- **Fixed Foobar2000 switching** — now uses correct `stop` → `play` within the running player instead of `taskkill + restart`\n- **Handled empty `genres`** — if `genre` matches exactly and `genres` is empty, stream gets position=0 (ideal match)\n- **Discovered and documented database bug** — the same stream could exist dozens of times with different `genre/genres`, breaking sort order\n\n### v2.1.0 (2026-05-27)\n\n- **Smart stream relevance sorting** — 3-level selection system:\n  1. Requested genre position in `genres` field\n  2. Number of extra subgenres\n  3. Stream speed\n- **Foobar2000 path auto-detection** — automatically finds installation in `Program Files` and `Program Files (x86)`\n- **Added `lounge` genre** to mood map (chill/sunset/evening pattern)\n- **Added Russian word \"кантри\"** to mood map\n- **Support for `genres` as string** — parsing via comma and semicolon\n- Updated documentation with stream selection algorithm description\n\n### v2.0.0\n\n- Initial release\n\nFile v2.5.0:_meta.json\n\n{\n  \"ownerId\": \"kn775k2zzav7y8rpwwm218x0b587f0hj\",\n  \"slug\": \"internet-radio-music-player\",\n  \"version\": \"2.5.0\",\n  \"publishedAt\": 1780053202799\n}\n\nFile v2.5.0:skill-card.md\n\n## Description: <br>\nInternet radio stream player via Foobar2000 with smart genre relevance sorting, play/stop/next/prev/resume controls, playback history filters and export, and a required Internet Radio Music DB companion skill. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[dynamicsalex](https://clawhub.ai/user/dynamicsalex) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users and developers use this skill to let an agent select internet radio streams by mood or genre, control Foobar2000 playback, and inspect or export local playback history. It is intended for environments where Foobar2000 and the Internet Radio Music DB skill are installed. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill gives an agent control over local Foobar2000 playback and internet radio stream selection. <br>\nMitigation: Install it only when agent-controlled media playback is desired, and keep agent commands scoped to explicit music playback requests. <br>\nRisk: Playback history is stored locally in the skill state file. <br>\nMitigation: Review local state retention expectations and avoid sharing the state file if listening history is sensitive. <br>\nRisk: The optional WebUI plugin exposes a localhost panel for playback and database management. <br>\nMitigation: Review the separate WebUI plugin before embedding or exposing its local panel. <br>\n\n\n## Reference(s): <br>\n- [Internet Radio Music Player ClawHub Page](https://clawhub.ai/dynamicsalex/internet-radio-music-player) <br>\n- [Internet Radio Music WebUI Plugin](https://clawhub.ai/dynamicsAlex/internet-radio-music-webui) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Text, Shell commands, Files, Configuration] <br>\n**Output Format:** [Plain text status and history output, shell command invocations, and optional CSV, HTML, or JSON history exports] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Controls local Foobar2000 playback and writes current playback state and history to state.json.] <br>\n\n## Skill Version(s): <br>\n2.5.0 (source: SKILL.md frontmatter and server release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v2.5.0:state.json\n\n{\r\n  \"History\": [\r\n    {\r\n      \"Time\": \"2026-05-28 20:23:11\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"01:25:03\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-28 21:48:17\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Spirit Country Radio\",\r\n      \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n      \"Duration\": \"00:44:06\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-28 22:43:31\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 09:14:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Spirit Country Radio\",\r\n      \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n      \"Duration\": \"00:04:16\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 09:18:43\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"01:27:13\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 10:45:59\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"All Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8024/stream\",\r\n      \"Duration\": \"00:19:22\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:05:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"00:36:58\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:36\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:03\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:43\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:50\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:19\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:12\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:10\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:25\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:10\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:38\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:08\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:49\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:45:09\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"00:00:12\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:45:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"All Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8024/stream\",\r\n      \"Duration\": \"00:00:20\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:46:19\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:12\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:22\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:04\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:29\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:36\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:43\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:05\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:51\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:12\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:14:06\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:06\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:28:44\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:19:22\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:48:09\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:03:14\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:51:39\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:07\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:51:52\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:05\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:52:37\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:26:53\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 13:19:48\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"01:33:08\"\r\n    }\r\n  ],\r\n  \"CurrentGenre\": \"ambient\",\r\n  \"CurrentIndex\": 0,\r\n  \"Volume\": 50,\r\n  \"CurrentStream\": null,\r\n  \"Stopped\": true\r\n}\n\nArchive v2.4.0: 6 files, 16035 bytes\n\nFiles: _meta.json (146b), scripts/play_music.py (21152b), scripts/show_history.py (11760b), skill-card.md (2525b), SKILL.md (8606b), state.json (6310b)\n\nFile v2.4.0:SKILL.md\n\n---\nname: internet-radio-music-player\nversion: 2.4.0\ndescription: Internet radio stream player via Foobar2000. Smart 4-level relevance sorting by genre. Supports: play/stop/next/prev/resume, playback history with filters and export. Requires the Internet Radio Music DB skill.\nsummary: Internet radio stream player via Foobar2000. Plays music by mood, selecting genre and stream from the Internet Radio Music DB with playback controls and history.\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n    emoji: \"🎶\"\n    homepage: https://clawhub.ai/skills/internet-radio-music-player\n---\n\n# Internet Radio Music Player\n\n**⚠️ WARNING: This skill REQUIRES the Internet Radio Music DB skill to work!**\n\nWithout the stream database skill installed, playback is impossible.\n\n## Install dependencies\n\n```bash\n# 1. Install the stream database skill (required!)\nopenclaw skills install internet-radio-music-db\n\n# 2. Restart Gateway\nopenclaw gateway restart\n```\n\n## How it works\n\n1. User specifies a mood (e.g. \"play happy music\")\n2. Skill determines suitable genres from the mood map\n3. **Streams are fetched from the Internet Radio Music DB** (`~/.openclaw/skills/internet-radio-music-db/state.json`)\n4. Streams are sorted by relevance to the requested genre (see algorithm below)\n5. Stream availability is checked (HTTP request)\n6. Foobar2000 is launched with the found URL\n7. History is saved to `state.json`\n\n## Stream selection algorithm\n\nWhen selecting a stream from the database, a 4-level relevance sorting is applied:\n\n### 1. Primary `genre` match (highest priority)\n\nStreams with an exact `genre` match (database field) are always ranked higher than those matched only via the `genres` list.\n\n### 2. Genre position in `genres` field\n\nThe requested genre is searched in the stream's `genres` list. The **closer to the beginning** — the higher the priority. If `genre` matches exactly and `genres` is empty — position=0 (ideal).\n\nExample: requested `ambient`\n- `genre=ambient, genres=[]` → level=0, position=0 ✅\n- `genre=chill, genres=[\"Ambient\", \"Chill\", \"Downtempo\"]` → level=1, position=0\n- `genre=rock, genres=[\"Downtempo\", \"Chill\", \"Ambient\"]` → level=1, position=2\n\n### 3. Number of \"extra\" genres\n\nGiven equal level and position — the stream with **fewer subgenres** wins.\n\n### 4. Stream speed\n\nAll other things being equal — the **faster** stream is chosen.\n\n### Final sort key\n\n```\n(genre_match_level, position, extra_genres, -speed)\n```\n\nLower value = more relevant stream.\n\n### `next` command\n\nSwitches to the next stream **of the same genre** from the database (using relevance sorting). Does not switch to a history entry.\n\n## Mood → Genres\n\n| Mood (keywords) | Genres from DB |\n|-----------------|----------------|\n| calm, sleep, rest, background, meditation | ambient, classical, folk |\n| happy, fun, dance, energy | dance, disco, pop, funk, house |\n| sad, blues, melancholy | blues, jazz, soul, ambient |\n| rock, hard, garage | rock, metal, punk, alternative, indie |\n| electronic, synth, lo-fi, dream | electronic, ambient, house, techno |\n| classical, orchestra, symphony | classical |\n| reggae, tropical, summer | reggae, latin, disco |\n| hip-hop, rap, R&B, soul | soul, funk, pop, disco |\n| techno, rave, club, trance | techno, house, trance, electronic, dance |\n| jazz, swing | jazz, blues, soul |\n| country, western, folk | country, folk |\n| lounge, chill-out | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| metal, heavy, power, aggression | metal, punk, rock |\n| 80s, 90s, retro, nostalgia | 80s, 90s, oldies, disco, pop |\n| indie, alternative, experimental | indie, alternative |\n| latin, salsa, bachata, brazil | latin |\n| pop, popular, hits | pop, top-40 |\n| work, focus, study | ambient, classical, electronic |\n| party, dancefloor | dance, house, techno, pop, funk, disco |\n| sunset, chill, evening, lounge | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| news, talk, podcast | news, talk |\n| gospel, church, spiritual | gospel, classical, ambient |\n\n## Commands\n\n| Command | Action |\n|---------|--------|\n| **\"Play music\"** | Play ambient (by default) |\n| **\"Play [mood] music\"** | Determine genre and play |\n| **\"Play jazz\" / \"Play sad music\"** | Jazz / blues |\n| **\"Play happy music\"** | Dance / disco / pop |\n| **\"Play music for sleeping\"** | Ambient / classical |\n| **\"Play rock\" / \"Play heavy music\"** | Rock / metal |\n| **\"Play electronic music\"** | Electronic / techno |\n| **\"Play reggae\" / \"Play summer music\"** | Reggae / latin |\n| **\"Play classical\"** | Classical |\n| **\"Play 80s music\"** | 80s |\n| **\"Next\" / \"Other stream\"** | Next stream of same genre |\n| **\"Previous\" / \"Back\"** | Return to previous stream |\n| **\"Play what was playing\" / \"Last stream\"** | Play the most recent stream from all history |\n| **\"Stop\"** | Stop playback |\n| **\"What's playing?\" / \"Status\"** | Show current stream |\n| **\"History\" / \"Playback list\"** | Show history |\n\n## Stream source\n\n**Music Stream Database** (`~/.openclaw/skills/internet-radio-music-db/`):\n- ~1000+ streams from 29 genres\n- Auto-populated every 3 hours from internet-radio.com\n- 29 genres collected in parallel\n- Streams are speed-checked during population (60 workers, 4 sec)\n- Streams with `failed_checks >= 3` are automatically removed from the database\n\n## Files\n\n| File | Purpose |\n|------|---------|\n| `scripts/play_music.py` | Main playback script (play/stop/next/prev/resume/status/history) |\n| `scripts/show_history.py` | Detailed playback history with filters and export (CSV/HTML/JSON) |\n| `state.json` | Current genre, playback history, current stream |\n| `~/.openclaw/skills/internet-radio-music-db/state.json` | Stream database (managed by Internet Radio Music DB skill) |\n\n## Dependencies\n\n- **Python 3** — for playback scripts\n- **Foobar2000** — music player (auto-detects path: `C:\\Program Files\\foobar2000\\` or `C:\\Program Files (x86)\\foobar2000\\`)\n- **Internet Radio Music DB** — stream database skill (required!)\n\n## Changelog\n\n### v2.4.0 (2026-05-29)\n\n- **Smart `play` after `stop` — auto-resume:** if playback was stopped via `stop`, pressing `play` without specifying a mood/genre resumes the last played stream from history instead of starting a new random one. State tracks `Stopped` flag to distinguish between \"never played\" and \"explicitly stopped\".\n- **Changed `--mood` default** from `\"ambient\"` to `None` — allows detecting when no genre was explicitly requested by the user. Internal fallback to `\"ambient\"` still applies when playing a new stream.\n- Updated `cmd_play` signature: entered genre always resets `Stopped` flag, ensuring explicit genre requests always start fresh.\n\n### v2.3.0 (2026-05-27)\n\n- **Removed `random.shuffle`** — previously, streams were shuffled after relevance sorting, causing multi-genre streams with a different primary genre (e.g. dance) to play instead of pure genre matches (e.g. country). Now the relevance order is always respected: pure genres first, multi-genre second.\n- Updated documentation with bug description and fix details\n- Full English translation of SKILL.md\n\n### v2.2.0 (2026-05-27)\n\n- **Improved stream sorting — now 4 priority levels:**\n  1. Primary `genre` match (exact > only in `genres` > none)\n  2. Requested genre position in `genres` field (closer to start = better)\n  3. Number of extra subgenres (fewer = more precise)\n  4. Stream speed (faster = better)\n- **Fixed `next` command** — now selects a stream from the database by current stream's genre (instead of random history switching). Uses the same relevance logic as `play`\n- **Fixed Foobar2000 switching** — now uses correct `stop` → `play` within the running player instead of `taskkill + restart`\n- **Handled empty `genres`** — if `genre` matches exactly and `genres` is empty, stream gets position=0 (ideal match)\n- **Discovered and documented database bug** — the same stream could exist dozens of times with different `genre/genres`, breaking sort order\n\n### v2.1.0 (2026-05-27)\n\n- **Smart stream relevance sorting** — 3-level selection system:\n  1. Requested genre position in `genres` field\n  2. Number of extra subgenres\n  3. Stream speed\n- **Foobar2000 path auto-detection** — automatically finds installation in `Program Files` and `Program Files (x86)`\n- **Added `lounge` genre** to mood map (chill/sunset/evening pattern)\n- **Added Russian word \"кантри\"** to mood map\n- **Support for `genres` as string** — parsing via comma and semicolon\n- Updated documentation with stream selection algorithm description\n\n### v2.0.0\n\n- Initial release\n\nFile v2.4.0:_meta.json\n\n{\n  \"ownerId\": \"kn775k2zzav7y8rpwwm218x0b587f0hj\",\n  \"slug\": \"internet-radio-music-player\",\n  \"version\": \"2.4.0\",\n  \"publishedAt\": 1780045210563\n}\n\nFile v2.4.0:skill-card.md\n\n## Description: <br>\nInternet radio stream player via Foobar2000. Smart 4-level relevance sorting by genre. Supports: play/stop/next/prev/resume, playback history with filters and export. Requires the Internet Radio Music DB skill. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[dynamicsalex](https://clawhub.ai/user/dynamicsalex) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users can ask an agent to control Foobar2000 internet radio playback by mood or genre, including play, stop, next, previous, resume, status, and history workflows. The skill is useful when the Internet Radio Music DB skill is installed and local playback history or exports are acceptable. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill contacts third-party radio stream hosts and can open provided stream URLs during playback. <br>\nMitigation: Use trusted stream database entries or URLs only, and run it in environments where those outbound media connections are acceptable. <br>\nRisk: Playback changes control Foobar2000 and may stop the running Foobar2000 process. <br>\nMitigation: Install it only on machines where the agent is allowed to manage Foobar2000 playback and process state. <br>\nRisk: The skill stores local playback history and can export that history to files. <br>\nMitigation: Treat state and exported history files as potentially sensitive local activity records and share or retain them accordingly. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/dynamicsalex/internet-radio-music-player) <br>\n- [Declared skill homepage](https://clawhub.ai/skills/internet-radio-music-player) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Text, Shell commands, Files] <br>\n**Output Format:** [Plain text status and history output, with optional CSV, HTML, or JSON history exports] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Controls Foobar2000 playback, reads the Internet Radio Music DB state file, and updates local playback state and history.] <br>\n\n## Skill Version(s): <br>\n2.4.0 (source: frontmatter, server release evidence, changelog released 2026-05-29) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v2.4.0:state.json\n\n{\r\n  \"History\": [\r\n    {\r\n      \"Time\": \"2026-05-28 20:23:11\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"01:25:03\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-28 21:48:17\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Spirit Country Radio\",\r\n      \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n      \"Duration\": \"00:44:06\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-28 22:43:31\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 09:14:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Spirit Country Radio\",\r\n      \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n      \"Duration\": \"00:04:16\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 09:18:43\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"01:27:13\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 10:45:59\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"All Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8024/stream\",\r\n      \"Duration\": \"00:19:22\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:05:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"00:36:58\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:36\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:03\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:43\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:50\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:19\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:12\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:10\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:25\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:10\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:38\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:08\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:49\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:45:09\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"00:00:12\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:45:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"All Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8024/stream\",\r\n      \"Duration\": \"00:00:20\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:46:19\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:12\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:22\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:04\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:29\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:36\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:43\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:05\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:13:51\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:12\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:14:06\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:06\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:28:44\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:19:22\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:48:09\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:03:14\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:51:39\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:07\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:51:52\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:05\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 12:52:37\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": null\r\n    }\r\n  ],\r\n  \"CurrentGenre\": \"ambient\",\r\n  \"CurrentIndex\": 0,\r\n  \"Volume\": 50,\r\n  \"CurrentStream\": {\r\n    \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n    \"Name\": \"White Noise Radio\",\r\n    \"Genre\": \"ambient\",\r\n    \"StartedAt\": \"2026-05-29 12:52:37\"\r\n  },\r\n  \"Stopped\": false\r\n}\n\nArchive v2.3.1: 5 files, 14854 bytes\n\nFiles: scripts/play_music.py (20774b), scripts/show_history.py (11760b), skill-card.md (2400b), SKILL.md (7939b), _meta.json (146b)\n\nFile v2.3.1:SKILL.md\n\n---\nname: internet-radio-music-player\nversion: 2.3.0\ndescription: Internet radio stream player via Foobar2000. Smart 4-level relevance sorting by genre. Supports: play/stop/next/prev/resume, playback history with filters and export. Requires the Internet Radio Music DB skill.\nsummary: Internet radio stream player via Foobar2000. Plays music by mood, selecting genre and stream from the Internet Radio Music DB with playback controls and history.\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n    emoji: \"🎶\"\n    homepage: https://clawhub.ai/skills/internet-radio-music-player\n---\n\n# Internet Radio Music Player\n\n**⚠️ WARNING: This skill REQUIRES the Internet Radio Music DB skill to work!**\n\nWithout the stream database skill installed, playback is impossible.\n\n## Install dependencies\n\n```bash\n# 1. Install the stream database skill (required!)\nopenclaw skills install internet-radio-music-db\n\n# 2. Restart Gateway\nopenclaw gateway restart\n```\n\n## How it works\n\n1. User specifies a mood (e.g. \"play happy music\")\n2. Skill determines suitable genres from the mood map\n3. **Streams are fetched from the Internet Radio Music DB** (`~/.openclaw/skills/internet-radio-music-db/state.json`)\n4. Streams are sorted by relevance to the requested genre (see algorithm below)\n5. Stream availability is checked (HTTP request)\n6. Foobar2000 is launched with the found URL\n7. History is saved to `state.json`\n\n## Stream selection algorithm\n\nWhen selecting a stream from the database, a 4-level relevance sorting is applied:\n\n### 1. Primary `genre` match (highest priority)\n\nStreams with an exact `genre` match (database field) are always ranked higher than those matched only via the `genres` list.\n\n### 2. Genre position in `genres` field\n\nThe requested genre is searched in the stream's `genres` list. The **closer to the beginning** — the higher the priority. If `genre` matches exactly and `genres` is empty — position=0 (ideal).\n\nExample: requested `ambient`\n- `genre=ambient, genres=[]` → level=0, position=0 ✅\n- `genre=chill, genres=[\"Ambient\", \"Chill\", \"Downtempo\"]` → level=1, position=0\n- `genre=rock, genres=[\"Downtempo\", \"Chill\", \"Ambient\"]` → level=1, position=2\n\n### 3. Number of \"extra\" genres\n\nGiven equal level and position — the stream with **fewer subgenres** wins.\n\n### 4. Stream speed\n\nAll other things being equal — the **faster** stream is chosen.\n\n### Final sort key\n\n```\n(genre_match_level, position, extra_genres, -speed)\n```\n\nLower value = more relevant stream.\n\n### `next` command\n\nSwitches to the next stream **of the same genre** from the database (using relevance sorting). Does not switch to a history entry.\n\n## Mood → Genres\n\n| Mood (keywords) | Genres from DB |\n|-----------------|----------------|\n| calm, sleep, rest, background, meditation | ambient, classical, folk |\n| happy, fun, dance, energy | dance, disco, pop, funk, house |\n| sad, blues, melancholy | blues, jazz, soul, ambient |\n| rock, hard, garage | rock, metal, punk, alternative, indie |\n| electronic, synth, lo-fi, dream | electronic, ambient, house, techno |\n| classical, orchestra, symphony | classical |\n| reggae, tropical, summer | reggae, latin, disco |\n| hip-hop, rap, R&B, soul | soul, funk, pop, disco |\n| techno, rave, club, trance | techno, house, trance, electronic, dance |\n| jazz, swing | jazz, blues, soul |\n| country, western, folk | country, folk |\n| lounge, chill-out | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| metal, heavy, power, aggression | metal, punk, rock |\n| 80s, 90s, retro, nostalgia | 80s, 90s, oldies, disco, pop |\n| indie, alternative, experimental | indie, alternative |\n| latin, salsa, bachata, brazil | latin |\n| pop, popular, hits | pop, top-40 |\n| work, focus, study | ambient, classical, electronic |\n| party, dancefloor | dance, house, techno, pop, funk, disco |\n| sunset, chill, evening, lounge | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| news, talk, podcast | news, talk |\n| gospel, church, spiritual | gospel, classical, ambient |\n\n## Commands\n\n| Command | Action |\n|---------|--------|\n| **\"Play music\"** | Play ambient (by default) |\n| **\"Play [mood] music\"** | Determine genre and play |\n| **\"Play jazz\" / \"Play sad music\"** | Jazz / blues |\n| **\"Play happy music\"** | Dance / disco / pop |\n| **\"Play music for sleeping\"** | Ambient / classical |\n| **\"Play rock\" / \"Play heavy music\"** | Rock / metal |\n| **\"Play electronic music\"** | Electronic / techno |\n| **\"Play reggae\" / \"Play summer music\"** | Reggae / latin |\n| **\"Play classical\"** | Classical |\n| **\"Play 80s music\"** | 80s |\n| **\"Next\" / \"Other stream\"** | Next stream of same genre |\n| **\"Previous\" / \"Back\"** | Return to previous stream |\n| **\"Play what was playing\" / \"Last stream\"** | Play the most recent stream from all history |\n| **\"Stop\"** | Stop playback |\n| **\"What's playing?\" / \"Status\"** | Show current stream |\n| **\"History\" / \"Playback list\"** | Show history |\n\n## Stream source\n\n**Music Stream Database** (`~/.openclaw/skills/internet-radio-music-db/`):\n- ~1000+ streams from 29 genres\n- Auto-populated every 3 hours from internet-radio.com\n- 29 genres collected in parallel\n- Streams are speed-checked during population (60 workers, 4 sec)\n- Streams with `failed_checks >= 3` are automatically removed from the database\n\n## Files\n\n| File | Purpose |\n|------|---------|\n| `scripts/play_music.py` | Main playback script (play/stop/next/prev/resume/status/history) |\n| `scripts/show_history.py` | Detailed playback history with filters and export (CSV/HTML/JSON) |\n| `state.json` | Current genre, playback history, current stream |\n| `~/.openclaw/skills/internet-radio-music-db/state.json` | Stream database (managed by Internet Radio Music DB skill) |\n\n## Dependencies\n\n- **Python 3** — for playback scripts\n- **Foobar2000** — music player (auto-detects path: `C:\\Program Files\\foobar2000\\` or `C:\\Program Files (x86)\\foobar2000\\`)\n- **Internet Radio Music DB** — stream database skill (required!)\n\n## Changelog\n\n### v2.3.0 (2026-05-27)\n\n- **Removed `random.shuffle`** — previously, streams were shuffled after relevance sorting, causing multi-genre streams with a different primary genre (e.g. dance) to play instead of pure genre matches (e.g. country). Now the relevance order is always respected: pure genres first, multi-genre second.\n- Updated documentation with bug description and fix details\n- Full English translation of SKILL.md\n\n### v2.2.0 (2026-05-27)\n\n- **Improved stream sorting — now 4 priority levels:**\n  1. Primary `genre` match (exact > only in `genres` > none)\n  2. Requested genre position in `genres` field (closer to start = better)\n  3. Number of extra subgenres (fewer = more precise)\n  4. Stream speed (faster = better)\n- **Fixed `next` command** — now selects a stream from the database by current stream's genre (instead of random history switching). Uses the same relevance logic as `play`\n- **Fixed Foobar2000 switching** — now uses correct `stop` → `play` within the running player instead of `taskkill + restart`\n- **Handled empty `genres`** — if `genre` matches exactly and `genres` is empty, stream gets position=0 (ideal match)\n- **Discovered and documented database bug** — the same stream could exist dozens of times with different `genre/genres`, breaking sort order\n\n### v2.1.0 (2026-05-27)\n\n- **Smart stream relevance sorting** — 3-level selection system:\n  1. Requested genre position in `genres` field\n  2. Number of extra subgenres\n  3. Stream speed\n- **Foobar2000 path auto-detection** — automatically finds installation in `Program Files` and `Program Files (x86)`\n- **Added `lounge` genre** to mood map (chill/sunset/evening pattern)\n- **Added Russian word \"кантри\"** to mood map\n- **Support for `genres` as string** — parsing via comma and semicolon\n- Updated documentation with stream selection algorithm description\n\n### v2.0.0\n\n- Initial release\n\nFile v2.3.1:_meta.json\n\n{\n  \"ownerId\": \"kn775k2zzav7y8rpwwm218x0b587f0hj\",\n  \"slug\": \"internet-radio-music-player\",\n  \"version\": \"2.3.1\",\n  \"publishedAt\": 1779899829469\n}\n\nFile v2.3.1:skill-card.md\n\n## Description: <br>\nPlays internet radio streams via Foobar2000 based on mood, selecting a genre and stream from the Internet Radio Music DB with playback controls and history support. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[dynamicsalex](https://clawhub.ai/user/dynamicsalex) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users use this skill to start mood-based internet radio playback in Foobar2000, move between streams, stop or resume playback, and review or export listening history. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill controls Foobar2000 and makes network requests to internet radio stream URLs. <br>\nMitigation: Install only if local media-player control and outbound stream requests are acceptable; prefer database-backed streams and avoid untrusted custom stream URLs. <br>\nRisk: Playback history is stored locally and may contain stream names, URLs, genres, timestamps, and notes. <br>\nMitigation: Review local history before sharing exports or the machine, and remove history entries that should not be retained. <br>\nRisk: HTML history exports may include stream metadata from external sources. <br>\nMitigation: Avoid opening HTML exports created from untrusted stream metadata until exported fields are safely escaped; use CSV or JSON exports when appropriate. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/dynamicsalex/internet-radio-music-player) <br>\n- [Declared homepage](https://clawhub.ai/skills/internet-radio-music-player) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Text, Shell commands, Files, Configuration] <br>\n**Output Format:** [Plain text command results, local state JSON, and optional CSV, HTML, or JSON history exports] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Controls Foobar2000, makes stream availability requests, and stores playback history locally.] <br>\n\n## Skill Version(s): <br>\n2.3.1 (source: server release metadata; artifact frontmatter lists 2.3.0) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v2.3.0: 5 files, 14749 bytes\n\nFiles: scripts/play_music.py (20774b), scripts/show_history.py (11760b), skill-card.md (2262b), SKILL.md (7768b), _meta.json (146b)\n\nFile v2.3.0:SKILL.md\n\n---\nname: internet-radio-music-player\nversion: 2.3.0\ndescription: Internet radio stream player via Foobar2000. Smart 4-level relevance sorting by genre. Supports: play/stop/next/prev/resume, playback history with filters and export. Requires the Internet Radio Music DB skill.\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n    emoji: \"🎶\"\n    homepage: https://clawhub.ai/skills/internet-radio-music-player\n---\n\n# Internet Radio Music Player\n\n**⚠️ WARNING: This skill REQUIRES the Internet Radio Music DB skill to work!**\n\nWithout the stream database skill installed, playback is impossible.\n\n## Install dependencies\n\n```bash\n# 1. Install the stream database skill (required!)\nopenclaw skills install internet-radio-music-db\n\n# 2. Restart Gateway\nopenclaw gateway restart\n```\n\n## How it works\n\n1. User specifies a mood (e.g. \"play happy music\")\n2. Skill determines suitable genres from the mood map\n3. **Streams are fetched from the Internet Radio Music DB** (`~/.openclaw/skills/internet-radio-music-db/state.json`)\n4. Streams are sorted by relevance to the requested genre (see algorithm below)\n5. Stream availability is checked (HTTP request)\n6. Foobar2000 is launched with the found URL\n7. History is saved to `state.json`\n\n## Stream selection algorithm\n\nWhen selecting a stream from the database, a 4-level relevance sorting is applied:\n\n### 1. Primary `genre` match (highest priority)\n\nStreams with an exact `genre` match (database field) are always ranked higher than those matched only via the `genres` list.\n\n### 2. Genre position in `genres` field\n\nThe requested genre is searched in the stream's `genres` list. The **closer to the beginning** — the higher the priority. If `genre` matches exactly and `genres` is empty — position=0 (ideal).\n\nExample: requested `ambient`\n- `genre=ambient, genres=[]` → level=0, position=0 ✅\n- `genre=chill, genres=[\"Ambient\", \"Chill\", \"Downtempo\"]` → level=1, position=0\n- `genre=rock, genres=[\"Downtempo\", \"Chill\", \"Ambient\"]` → level=1, position=2\n\n### 3. Number of \"extra\" genres\n\nGiven equal level and position — the stream with **fewer subgenres** wins.\n\n### 4. Stream speed\n\nAll other things being equal — the **faster** stream is chosen.\n\n### Final sort key\n\n```\n(genre_match_level, position, extra_genres, -speed)\n```\n\nLower value = more relevant stream.\n\n### `next` command\n\nSwitches to the next stream **of the same genre** from the database (using relevance sorting). Does not switch to a history entry.\n\n## Mood → Genres\n\n| Mood (keywords) | Genres from DB |\n|-----------------|----------------|\n| calm, sleep, rest, background, meditation | ambient, classical, folk |\n| happy, fun, dance, energy | dance, disco, pop, funk, house |\n| sad, blues, melancholy | blues, jazz, soul, ambient |\n| rock, hard, garage | rock, metal, punk, alternative, indie |\n| electronic, synth, lo-fi, dream | electronic, ambient, house, techno |\n| classical, orchestra, symphony | classical |\n| reggae, tropical, summer | reggae, latin, disco |\n| hip-hop, rap, R&B, soul | soul, funk, pop, disco |\n| techno, rave, club, trance | techno, house, trance, electronic, dance |\n| jazz, swing | jazz, blues, soul |\n| country, western, folk | country, folk |\n| lounge, chill-out | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| metal, heavy, power, aggression | metal, punk, rock |\n| 80s, 90s, retro, nostalgia | 80s, 90s, oldies, disco, pop |\n| indie, alternative, experimental | indie, alternative |\n| latin, salsa, bachata, brazil | latin |\n| pop, popular, hits | pop, top-40 |\n| work, focus, study | ambient, classical, electronic |\n| party, dancefloor | dance, house, techno, pop, funk, disco |\n| sunset, chill, evening, lounge | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| news, talk, podcast | news, talk |\n| gospel, church, spiritual | gospel, classical, ambient |\n\n## Commands\n\n| Command | Action |\n|---------|--------|\n| **\"Play music\"** | Play ambient (by default) |\n| **\"Play [mood] music\"** | Determine genre and play |\n| **\"Play jazz\" / \"Play sad music\"** | Jazz / blues |\n| **\"Play happy music\"** | Dance / disco / pop |\n| **\"Play music for sleeping\"** | Ambient / classical |\n| **\"Play rock\" / \"Play heavy music\"** | Rock / metal |\n| **\"Play electronic music\"** | Electronic / techno |\n| **\"Play reggae\" / \"Play summer music\"** | Reggae / latin |\n| **\"Play classical\"** | Classical |\n| **\"Play 80s music\"** | 80s |\n| **\"Next\" / \"Other stream\"** | Next stream of same genre |\n| **\"Previous\" / \"Back\"** | Return to previous stream |\n| **\"Play what was playing\" / \"Last stream\"** | Play the most recent stream from all history |\n| **\"Stop\"** | Stop playback |\n| **\"What's playing?\" / \"Status\"** | Show current stream |\n| **\"History\" / \"Playback list\"** | Show history |\n\n## Stream source\n\n**Music Stream Database** (`~/.openclaw/skills/internet-radio-music-db/`):\n- ~1000+ streams from 29 genres\n- Auto-populated every 3 hours from internet-radio.com\n- 29 genres collected in parallel\n- Streams are speed-checked during population (60 workers, 4 sec)\n- Streams with `failed_checks >= 3` are automatically removed from the database\n\n## Files\n\n| File | Purpose |\n|------|---------|\n| `scripts/play_music.py` | Main playback script (play/stop/next/prev/resume/status/history) |\n| `scripts/show_history.py` | Detailed playback history with filters and export (CSV/HTML/JSON) |\n| `state.json` | Current genre, playback history, current stream |\n| `~/.openclaw/skills/internet-radio-music-db/state.json` | Stream database (managed by Internet Radio Music DB skill) |\n\n## Dependencies\n\n- **Python 3** — for playback scripts\n- **Foobar2000** — music player (auto-detects path: `C:\\Program Files\\foobar2000\\` or `C:\\Program Files (x86)\\foobar2000\\`)\n- **Internet Radio Music DB** — stream database skill (required!)\n\n## Changelog\n\n### v2.3.0 (2026-05-27)\n\n- **Removed `random.shuffle`** — previously, streams were shuffled after relevance sorting, causing multi-genre streams with a different primary genre (e.g. dance) to play instead of pure genre matches (e.g. country). Now the relevance order is always respected: pure genres first, multi-genre second.\n- Updated documentation with bug description and fix details\n- Full English translation of SKILL.md\n\n### v2.2.0 (2026-05-27)\n\n- **Improved stream sorting — now 4 priority levels:**\n  1. Primary `genre` match (exact > only in `genres` > none)\n  2. Requested genre position in `genres` field (closer to start = better)\n  3. Number of extra subgenres (fewer = more precise)\n  4. Stream speed (faster = better)\n- **Fixed `next` command** — now selects a stream from the database by current stream's genre (instead of random history switching). Uses the same relevance logic as `play`\n- **Fixed Foobar2000 switching** — now uses correct `stop` → `play` within the running player instead of `taskkill + restart`\n- **Handled empty `genres`** — if `genre` matches exactly and `genres` is empty, stream gets position=0 (ideal match)\n- **Discovered and documented database bug** — the same stream could exist dozens of times with different `genre/genres`, breaking sort order\n\n### v2.1.0 (2026-05-27)\n\n- **Smart stream relevance sorting** — 3-level selection system:\n  1. Requested genre position in `genres` field\n  2. Number of extra subgenres\n  3. Stream speed\n- **Foobar2000 path auto-detection** — automatically finds installation in `Program Files` and `Program Files (x86)`\n- **Added `lounge` genre** to mood map (chill/sunset/evening pattern)\n- **Added Russian word \"кантри\"** to mood map\n- **Support for `genres` as string** — parsing via comma and semicolon\n- Updated documentation with stream selection algorithm description\n\n### v2.0.0\n\n- Initial release\n\nFile v2.3.0:_meta.json\n\n{\n  \"ownerId\": \"kn775k2zzav7y8rpwwm218x0b587f0hj\",\n  \"slug\": \"internet-radio-music-player\",\n  \"version\": \"2.3.0\",\n  \"publishedAt\": 1779899200721\n}\n\nFile v2.3.0:skill-card.md\n\n## Description: <br>\nPlays internet radio streams through Foobar2000, selecting mood- or genre-matched streams from Internet Radio Music DB and supporting playback control plus history export. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[dynamicsalex](https://clawhub.ai/user/dynamicsalex) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users use this skill to control Foobar2000 internet radio playback by mood or genre, move between streams, resume previous streams, and inspect or export playback history. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Generic commands such as stop and next can be triggered unintentionally. <br>\nMitigation: Configure the agent to route these commands to this skill only when the user intends to control radio playback. <br>\nRisk: The skill stores playback history locally, including stream names, URLs, genres, and timestamps. <br>\nMitigation: Review local state files before sharing a system or exporting history, and clear history when retention is not desired. <br>\nRisk: The skill contacts selected stream URLs to test availability and then launches playback through Foobar2000. <br>\nMitigation: Install it only in environments where Foobar2000 playback and outbound stream requests are expected. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/dynamicsalex/internet-radio-music-player) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, shell commands, files] <br>\n**Output Format:** [Plain text playback status and history output, with optional CSV, HTML, or JSON history exports.] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Writes local state and playback history; stream selection depends on the Internet Radio Music DB skill and Foobar2000 availability.] <br>\n\n## Skill Version(s): <br>\n2.3.0 (source: frontmatter and server release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v2.2.0: 6 files, 16510 bytes\n\nFiles: _meta.json (146b), scripts/play_music.py (20803b), scripts/show_history.py (11760b), skill-card.md (2117b), SKILL.md (11788b), state.json (5584b)\n\nFile v2.2.0:SKILL.md\n\n---\nname: internet-radio-music-player\nversion: 2.2.0\ndescription: Воспроизведение интернет-радио через Foobar2000. Умная 4-уровневая сортировка потоков по релевантности жанра. Поддерживает: play/stop/next/prev, историю прослушиваний. Для работы обязательно требуется скилл Internet Radio Music DB.\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n    emoji: \"🎶\"\n    homepage: https://clawhub.ai/skills/internet-radio-music-player\n---\n\n# Internet Radio Music Player\n\n**⚠️ ВНИМАНИЕ: Для работы этого скилла ОБЯЗАТЕЛЬНО требуется скилл Internet Radio Music DB!**\n\nБез установленного скилла базы потоков воспроизведение невозможно.\n\n## Установка зависимостей\n\n```bash\n# 1. Установить базу потоков (обязательно!)\nopenclaw skills install internet-radio-music-db\n\n# 2. Перезапустить Gateway\nopenclaw gateway restart\n```\n\n## Принцип работы\n\n1. Пользователь задаёт настроение (например, «включи весёлую музыку»)\n2. Скилл определяет подходящие жанры из карты настроений\n3. **Потоки берутся из базы Internet Radio Music DB** (`~/.openclaw/skills/internet-radio-music-db/state.json`)\n4. Потоки сортируются по релевантности запрошенному жанру (см. алгоритм ниже)\n5. Проверяется доступность потока (HTTP-запрос)\n6. Запускается Foobar2000 с найденным URL\n7. История сохраняется в `state.json`\n\n## Алгоритм выбора потока\n\nПри выборе потока из базы применяется 4-уровневая сортировка по релевантности:\n\n### 1. Совпадение основного `genre` (высший приоритет)\n\nПотоки с точным совпадением `genre` (поле базы) всегда выше тех, где жанр совпал только по списку `genres`.\n\n### 2. Позиция жанра в поле `genres`\n\nЗапрошенный жанр ищется в списке `genres` потока. Чем **ближе к началу** — тем выше приоритет. Если `genre` совпал точно и `genres` пустой — position=0 (идеально).\n\nПример: запрошен `ambient`\n- `genre=ambient, genres=[]` → level=0, position=0 ✅\n- `genre=chill, genres=[\"Ambient\", \"Chill\", \"Downtempo\"]` → level=1, position=0\n- `genre=rock, genres=[\"Downtempo\", \"Chill\", \"Ambient\"]` → level=1, position=2\n\n### 3. Количество «лишних» жанров\n\nПри равных уровне и позиции — выигрывает поток с **меньшим количеством поджанров**.\n\n### 4. Скорость потока\n\nПри прочих равных — выбирается **более быстрый** поток.\n\n### Итоговый ключ сортировки\n\n```\n(genre_match_level, position, extra_genres, -speed)\n```\n\nМеньшее значение = более подходящий поток.\n\n### Команда `next`\n\nПереключает на следующий поток **того же жанра** из базы (с учётом сортировки по релевантности). Не переключает на запись из истории.\n\n## Настроение → жанры\n\n| Настроение (ключевые слова) | Жанры из базы |\n|-----------------------------|---------------|\n| спокойная, засыпание, сон, отдых, фон, медитация | ambient, classical, folk |\n| весёлая, радостная, танцевальная, энергия | dance, disco, pop, funk, house |\n| грустная, печаль, блюз, меланхолия | blues, jazz, soul, ambient |\n| рок, тяжёлая, гараж, хард | rock, metal, punk, alternative, indie |\n| электронная, синтезатор, lo-fi, dream | electronic, ambient, house, techno |\n| классическая, оркестр, симфония, пианино | classical |\n| реггей, карибы, лето, тропики | reggae, latin, disco |\n| хип-хоп, рэп, R&B, соул | soul, funk, pop, disco |\n| техно, рейв, клуб, транс | techno, house, trance, electronic, dance |\n| джаз, свинг | jazz, blues, soul |\n| кантри, вестерн, фольклор | country, folk |\n| lounge, лаунж | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| метал, хэви, пауэр, агрессия | metal, punk, rock |\n| 80s, 90s, ностальгия, ретро, старые хиты | 80s, 90s, oldies, disco, pop |\n| инди, альтернатива, необычная, эксперимент | indie, alternative |\n| латин, сальса, бачата, бразилия | latin |\n| поп, популярная, хиты, радио | pop, top-40 |\n| для работы, концентрация, фокус, учёба | ambient, classical, electronic |\n| вечеринка, туса, драйв, кач | dance, house, techno, pop, funk, disco |\n| закат, расслабление, chill, вечер, lounge | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| новости, разговоры, подкасты | news, talk |\n| гимны, церковная, духовная | gospel, classical, ambient |\n\n## Команды\n\n| Команда | Действие |\n|---------|----------|\n| **«Включи музыку»** | Воспроизвести ambient (по умолчанию) |\n| **«Включи музыку [настроение]»** | Определить жанр и включить |\n| **«Включи джаз» / «Грустная музыка»** | Джаз / blues |\n| **«Включи весёлую музыку»** | Dance / disco / pop |\n| **«Включи музыку для засыпания»** | Ambient / classical |\n| **«Включи рок» / «Тяжёлую музыку»** | Rock / metal |\n| **«Включи электронную музыку»** | Electronic / techno |\n| **«Включи реггей» / «Летнюю музыку»** | Reggae / latin |\n| **«Включи классику»** | Classical |\n| **«Включи музыку 80-х»** | 80s |\n| **«Следующий» / «Другой поток»** | Следующий поток того же жанра |\n| **«Назад» / «Предыдущий»** | Вернуться к предыдущему потоку |\n| **«Включи то что играло» / «Последний поток»** | Воспроизвести последний поток из всей истории |\n| **«Стоп»** | Остановить воспроизведение |\n| **«Что играет?» / «Статус»** | Показать текущий поток |\n| **«История» / «Список прослушанных»** | Показать историю |\n\n## Источник потоков\n\n**База музыкальных потоков** (`~/.openclaw/skills/internet-radio-music-db/`):\n- ~2000+ потоков из 29 жанров\n- Автоматическое наполнение каждые 3 часа с internet-radio.com\n- Параллельный сбор 29 жанров одновременно\n- Потоки проверяются на скорость при наполнении (60 воркеров, 4 сек)\n- Потоки с `failed_checks >= 3` автоматически удаляются из базы\n\n## Файлы\n\n| Файл | Назначение |\n|------|-----------|\n| `scripts/play_music.py` | Основной скрипт воспроизведения (play/stop/next/prev/resume/status/history) |\n| `scripts/show_history.py` | Детальная история прослушиваний с фильтрами и экспортом |\n| `state.json` | Текущий жанр, история прослушиваний, текущий поток |\n| `~/.openclaw/skills/internet-radio-music-db/state.json` | База потоков (управляется скиллом Internet Radio Music DB) |\n\n## Зависимости\n\n- **Python 3** — для скриптов воспроизведения\n- **Foobar2000** — музыкальный проигрыватель (автоопределение пути: `C:\\Program Files\\foobar2000\\` или `C:\\Program Files (x86)\\foobar2000\\`)\n- **Internet Radio Music DB** — скилл базы потоков (обязательно!)\n\n## Чейнджлог\n\n### v2.1.0 (27.05.2026)\n\n- **Умная сортировка потоков по релевантности** — трёхуровневая система выбора:\n  1. Позиция запрошенного жанра в поле `genres` (чем ближе к началу — тем лучше)\n  2. Количество лишних поджанров (чем меньше — тем точнее)\n  3. Скорость потока (при равных условиях — быстрее)\n- **Автоопределение пути Foobar2000** — скрипт автоматически ищет установку в `Program Files` и `Program Files (x86)`\n- **Добавлен жанр `lounge`** в карту настроений (паттерн chill/sunset/evening)\n- **Добавлена поддержка русского слова «кантри»** в карту настроений\n- **Поддержка поля `genres` как строки** — парсинг через запятую и точку с запятой\n- Обновлена документация с описанием алгоритма выбора потока\n\n### v2.2.0 (27.05.2026)\n\n- **Улучшена сортировка потоков — теперь 4 уровня приоритета:**\n  1. Совпадение основного `genre` (точное > только в `genres` > нет)\n  2. Позиция запрошенного жанра в поле `genres` (ближе к началу = лучше)\n  3. Количество лишних поджанров (меньше = точнее)\n  4. Скорость потока (быстрее = лучше)\n- **Исправлена команда `next`** — теперь выбирает поток из базы по жанру текущего потока (вместо случайного переключения на запись из истории). Использует ту же логику релевантности что и `play`\n- **Исправлено переключение Foobar2000** — вместо `taskkill + restart` теперь корректный `stop` → `play` внутри работающего плеера\n- **Обработан пустой `genres`** — если `genre` совпал точно и `genres` пустой, поток получает position=0 (идеальное совпадение)\n- **Обнаружен и задокументирован баг базы** — один и тот же поток мог присутствовать десятками копий с разным `genre/genres`, что ломало сортировку\n\n### v2.0.0\n\n- Базовый релиз скилла\n\nFile v2.2.0:_meta.json\n\n{\n  \"ownerId\": \"kn775k2zzav7y8rpwwm218x0b587f0hj\",\n  \"slug\": \"internet-radio-music-player\",\n  \"version\": \"2.2.0\",\n  \"publishedAt\": 1779879348268\n}\n\nFile v2.2.0:skill-card.md\n\n## Description: <br>\nPlays internet radio streams through Foobar2000 based on mood or genre, selects streams from Internet Radio Music DB, and supports playback controls and listening history. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[dynamicsalex](https://clawhub.ai/user/dynamicsalex) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users and developers use this skill to let an agent choose and control internet radio playback through Foobar2000, including mood-to-genre selection, next/previous controls, status checks, and listening history. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill controls Foobar2000 and opens internet radio stream URLs. <br>\nMitigation: Install only in environments where agent-controlled playback is acceptable, and use explicit playback commands such as stop radio, radio status, and listening history. <br>\nRisk: The playurl command can open user-supplied URLs. <br>\nMitigation: Use trusted HTTP or HTTPS stream URLs and avoid local files or non-http URLs. <br>\nRisk: Listening history and current stream details are stored locally. <br>\nMitigation: Review or clear local state before sharing the skill directory or logs. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/dynamicsalex/internet-radio-music-player) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Text, Shell commands, Files, Configuration] <br>\n**Output Format:** [Plain text command output with optional CSV, HTML, or JSON history exports] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Stores current stream and listening history in local state.json.] <br>\n\n## Skill Version(s): <br>\n2.2.0 (source: frontmatter and server release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v2.2.0:state.json\n\n{\r\n  \"History\": [\r\n    {\r\n      \"Time\": \"2026-05-26 18:16:11\",\r\n      \"Genre\": \"jazz\",\r\n      \"Name\": \"1940s Radio Station\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8082/stream\",\r\n      \"Duration\": \"00:06:06\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 11:28:50\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"1940s Radio Station\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8082/stream\",\r\n      \"Duration\": null,\r\n      \"Note\": \"Mood: кантри\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 11:34:17\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Polymer Radio (Music supplied by the \\\"Free Music Archive\\\")\",\r\n      \"Url\": \"http://uk5.internet-radio.com:8185/stream\",\r\n      \"Duration\": \"00:00:16\",\r\n      \"Note\": \"Mood: кантри\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 11:34:34\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Ambient Radio .org - Deeply Beautiful Chillout Music - A Heavenly World of Sound\",\r\n      \"Url\": \"http://uk2.internet-radio.com:8171/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 11:36:02\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Radio Te Amo Mama Hilda\",\r\n      \"Url\": \"http://uk2.internet-radio.com:8028/stream\",\r\n      \"Duration\": null,\r\n      \"Note\": \"Mood: кантри\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 11:36:31\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Radio Te Amo Mama Hilda\",\r\n      \"Url\": \"http://uk2.internet-radio.com:8028/stream\",\r\n      \"Duration\": null,\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 11:51:53\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Radio Te Amo Mama Hilda\",\r\n      \"Url\": \"http://uk2.internet-radio.com:8028/stream\",\r\n      \"Duration\": null,\r\n      \"Note\": \"Mood: кантри\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 12:05:42\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": null,\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 12:07:12\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Radio Te Amo Mama Hilda\",\r\n      \"Url\": \"http://uk2.internet-radio.com:8028/stream\",\r\n      \"Duration\": null,\r\n      \"Note\": \"Mood: lounge\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 12:08:27\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brum Radio - Birmingham\",\r\n      \"Url\": \"http://uk3.internet-radio.com:11168/stream\",\r\n      \"Duration\": null,\r\n      \"Note\": \"Mood: lounge\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 12:17:35\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Real World Sounds\",\r\n      \"Url\": \"http://uk5.internet-radio.com:8260/stream\",\r\n      \"Duration\": null,\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 12:23:42\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Phoenix Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8076/stream\",\r\n      \"Duration\": \"01:58:53\",\r\n      \"Note\": \"Mood: кантри\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 14:22:36\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Radio Te Amo Mama Hilda\",\r\n      \"Url\": \"http://uk2.internet-radio.com:8028/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 14:27:42\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"All Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8024/stream\",\r\n      \"Duration\": \"00:00:23\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 14:28:06\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Radio Te Amo Mama Hilda\",\r\n      \"Url\": \"http://uk2.internet-radio.com:8028/stream\",\r\n      \"Duration\": \"00:02:50\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 14:30:57\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"All Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8024/stream\",\r\n      \"Duration\": \"00:04:30\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 14:35:28\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Radio Te Amo Mama Hilda\",\r\n      \"Url\": \"http://uk2.internet-radio.com:8028/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 14:37:01\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"All Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8024/stream\",\r\n      \"Duration\": \"00:00:26\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 14:37:28\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Spirit Country Radio\",\r\n      \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n      \"Duration\": \"00:05:28\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 14:42:59\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 14:45:02\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Radio Te Amo Mama Hilda\",\r\n      \"Url\": \"http://uk2.internet-radio.com:8028/stream\",\r\n      \"Duration\": null,\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 14:49:22\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"00:02:08\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 14:51:33\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Spirit Country Radio\",\r\n      \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n      \"Duration\": null\r\n    }\r\n  ],\r\n  \"CurrentGenre\": \"country\",\r\n  \"CurrentIndex\": 0,\r\n  \"Volume\": 50,\r\n  \"CurrentStream\": {\r\n    \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n    \"Name\": \"Spirit Country Radio\",\r\n    \"Genre\": \"country\",\r\n    \"StartedAt\": \"2026-05-27 14:51:33\"\r\n  }\r\n}\n\nArchive v2.1.0: 6 files, 15803 bytes\n\nFiles: _meta.json (146b), scripts/play_music.py (19560b), scripts/show_history.py (11760b), skill-card.md (2618b), SKILL.md (10190b), state.json (3166b)\n\nFile v2.1.0:SKILL.md\n\n---\nname: internet-radio-music-player\nversion: 2.1.0\ndescription: Воспроизведение интернет-радио через Foobar2000. Пользователь задаёт настроение, скилл определяет жанр, выбирает поток из базы Internet Radio Music DB и воспроизводит. Умная сортировка потоков по релевантности жанра. Поддерживает: play/stop/next/prev/resume, историю прослушиваний. Для работы обязательно требуется установленный скилл Internet Radio Music DB — без него воспроизведение невозможно.\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n    emoji: \"🎶\"\n    homepage: https://clawhub.ai/skills/internet-radio-music-player\n---\n\n# Internet Radio Music Player\n\n**⚠️ ВНИМАНИЕ: Для работы этого скилла ОБЯЗАТЕЛЬНО требуется скилл Internet Radio Music DB!**\n\nБез установленного скилла базы потоков воспроизведение невозможно.\n\n## Установка зависимостей\n\n```bash\n# 1. Установить базу потоков (обязательно!)\nopenclaw skills install internet-radio-music-db\n\n# 2. Перезапустить Gateway\nopenclaw gateway restart\n```\n\n## Принцип работы\n\n1. Пользователь задаёт настроение (например, «включи весёлую музыку»)\n2. Скилл определяет подходящие жанры из карты настроений\n3. **Потоки берутся из базы Internet Radio Music DB** (`~/.openclaw/skills/internet-radio-music-db/state.json`)\n4. Потоки сортируются по релевантности запрошенному жанру (см. алгоритм ниже)\n5. Проверяется доступность потока (HTTP-запрос)\n6. Запускается Foobar2000 с найденным URL\n7. История сохраняется в `state.json`\n\n## Алгоритм выбора потока\n\nПри выборе потока из базы применяется многоуровневая сортировка по релевантности:\n\n### 1. Позиция жанра в поле `genres` (высший приоритет)\n\nЗапрошенный жанр ищется в списке `genres` потока. Чем **ближе к началу** списка — тем выше приоритет.\n\nПример: запрошен `ambient`\n- `genres: [\"Ambient\", \"Chill\", \"Downtempo\"]` → позиция 0 ✅\n- `genres: [\"Downtempo\", \"Chill\", \"Ambient\"]` → позиция 2\n\nПобедит первый поток, так как `ambient` стоит на 1-й позиции.\n\n### 2. Количество «лишних» жанров\n\nПри равной позиции — выигрывает поток с **меньшим количеством поджанров** (более точное совпадение).\n\nПример:\n- `genres: [\"Ambient\", \"Chill\"]` → 1 лишний\n- `genres: [\"Ambient\", \"Chill\", \"Downtempo\"]` → 2 лишних\n\nПобедит первый.\n\n### 3. Скорость потока\n\nПри равных позиции и точности — выбирается **более быстрый** поток.\n\n### Итоговый ключ сортировки\n\n```\n(position, extra_genres, -speed)\n```\n\nМеньшее значение = более подходящий поток.\n\n## Настроение → жанры\n\n| Настроение (ключевые слова) | Жанры из базы |\n|-----------------------------|---------------|\n| спокойная, засыпание, сон, отдых, фон, медитация | ambient, classical, folk |\n| весёлая, радостная, танцевальная, энергия | dance, disco, pop, funk, house |\n| грустная, печаль, блюз, меланхолия | blues, jazz, soul, ambient |\n| рок, тяжёлая, гараж, хард | rock, metal, punk, alternative, indie |\n| электронная, синтезатор, lo-fi, dream | electronic, ambient, house, techno |\n| классическая, оркестр, симфония, пианино | classical |\n| реггей, карибы, лето, тропики | reggae, latin, disco |\n| хип-хоп, рэп, R&B, соул | soul, funk, pop, disco |\n| техно, рейв, клуб, транс | techno, house, trance, electronic, dance |\n| джаз, свинг | jazz, blues, soul |\n| кантри, вестерн, фольклор | country, folk |\n| lounge, лаунж | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| метал, хэви, пауэр, агрессия | metal, punk, rock |\n| 80s, 90s, ностальгия, ретро, старые хиты | 80s, 90s, oldies, disco, pop |\n| инди, альтернатива, необычная, эксперимент | indie, alternative |\n| латин, сальса, бачата, бразилия | latin |\n| поп, популярная, хиты, радио | pop, top-40 |\n| для работы, концентрация, фокус, учёба | ambient, classical, electronic |\n| вечеринка, туса, драйв, кач | dance, house, techno, pop, funk, disco |\n| закат, расслабление, chill, вечер, lounge | ambient, jazz, indie, folk, chill, lounge, downtempo, relaxation |\n| новости, разговоры, подкасты | news, talk |\n| гимны, церковная, духовная | gospel, classical, ambient |\n\n## Команды\n\n| Команда | Действие |\n|---------|----------|\n| **«Включи музыку»** | Воспроизвести ambient (по умолчанию) |\n| **«Включи музыку [настроение]»** | Определить жанр и включить |\n| **«Включи джаз» / «Грустная музыка»** | Джаз / blues |\n| **«Включи весёлую музыку»** | Dance / disco / pop |\n| **«Включи музыку для засыпания»** | Ambient / classical |\n| **«Включи рок» / «Тяжёлую музыку»** | Rock / metal |\n| **«Включи электронную музыку»** | Electronic / techno |\n| **«Включи реггей» / «Летнюю музыку»** | Reggae / latin |\n| **«Включи классику»** | Classical |\n| **«Включи музыку 80-х»** | 80s |\n| **«Следующий» / «Другой поток»** | Следующий поток того же жанра |\n| **«Назад» / «Предыдущий»** | Вернуться к предыдущему потоку |\n| **«Включи то что играло» / «Последний поток»** | Воспроизвести последний поток из всей истории |\n| **«Стоп»** | Остановить воспроизведение |\n| **«Что играет?» / «Статус»** | Показать текущий поток |\n| **«История» / «Список прослушанных»** | Показать историю |\n\n## Источник потоков\n\n**База музыкальных потоков** (`~/.openclaw/skills/internet-radio-music-db/`):\n- ~2000+ потоков из 29 жанров\n- Автоматическое наполнение каждые 3 часа с internet-radio.com\n- Параллельный сбор 29 жанров одновременно\n- Потоки проверяются на скорость при наполнении (60 воркеров, 4 сек)\n- Потоки с `failed_checks >= 3` автоматически удаляются из базы\n\n## Файлы\n\n| Файл | Назначение |\n|------|-----------|\n| `scripts/play_music.py` | Основной скрипт воспроизведения (play/stop/next/prev/resume/status/history) |\n| `scripts/show_history.py` | Детальная история прослушиваний с фильтрами и экспортом |\n| `state.json` | Текущий жанр, история прослушиваний, текущий поток |\n| `~/.openclaw/skills/internet-radio-music-db/state.json` | База потоков (управляется скиллом Internet Radio Music DB) |\n\n## Зависимости\n\n- **Python 3** — для скриптов воспроизведения\n- **Foobar2000** — музыкальный проигрыватель (автоопределение пути: `C:\\Program Files\\foobar2000\\` или `C:\\Program Files (x86)\\foobar2000\\`)\n- **Internet Radio Music DB** — скилл базы потоков (обязательно!)\n\n## Чейнджлог\n\n### v2.1.0 (27.05.2026)\n\n- **Умная сортировка потоков по релевантности** — трёхуровневая система выбора:\n  1. Позиция запрошенного жанра в поле `genres` (чем ближе к началу — тем лучше)\n  2. Количество лишних поджанров (чем меньше — тем точнее)\n  3. Скорость потока (при равных условиях — быстрее)\n- **Автоопределение пути Foobar2000** — скрипт автоматически ищет установку в `Program Files` и `Program Files (x86)`\n- **Добавлен жанр `lounge`** в карту настроений (паттерн chill/sunset/evening)\n- **Добавлена поддержка русского слова «кантри»** в карту настроений\n- **Поддержка поля `genres` как строки** — парсинг через запятую и точку с запятой\n- Обновлена документация с описанием алгоритма выбора потока\n\n### v2.0.0\n\n- Базовый релиз скилла\n\nFile v2.1.0:_meta.json\n\n{\n  \"ownerId\": \"kn775k2zzav7y8rpwwm218x0b587f0hj\",\n  \"slug\": \"internet-radio-music-player\",\n  \"version\": \"2.1.0\",\n  \"publishedAt\": 1779875835256\n}\n\nFile v2.1.0:skill-card.md\n\n## Description: <br>\nPlays internet radio streams through Foobar2000 by mapping a user's mood to a genre, selecting a stream from Internet Radio Music DB, and supporting playback controls and listening history. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[dynamicsalex](https://clawhub.ai/user/dynamicsalex) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal OpenClaw users use this skill to start, stop, resume, and browse internet radio streams by mood or genre through a local Foobar2000 player. It is useful for hands-free music playback when the Internet Radio Music DB dependency is installed. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill can pass unvalidated stream or user-supplied URLs to Foobar2000. <br>\nMitigation: Use trusted Internet Radio Music DB sources, avoid arbitrary playurl inputs, and review stream URLs before ambient or voice-triggered use. <br>\nRisk: The skill can stop existing Foobar2000 playback while starting or stopping streams. <br>\nMitigation: Install only where local Foobar2000 control is expected and acceptable for the user account running the agent. <br>\nRisk: Listening history is stored locally in state.json. <br>\nMitigation: Review local history retention expectations and remove state entries when they should not persist. <br>\nRisk: Broad voice commands may trigger playback controls unintentionally. <br>\nMitigation: Prefer narrower voice triggers such as \"следующий поток\" or \"останови радио\" before ambient voice use. <br>\n\n\n## Reference(s): <br>\n- [ClawHub skill page](https://clawhub.ai/dynamicsalex/internet-radio-music-player) <br>\n- [Skill homepage](https://clawhub.ai/skills/internet-radio-music-player) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, shell commands, configuration, guidance] <br>\n**Output Format:** [Plain text status messages, command output, and playback-history exports as CSV, HTML, or JSON] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Controls local Foobar2000 playback, reads stream metadata from Internet Radio Music DB, and stores listening history in state.json.] <br>\n\n## Skill Version(s): <br>\n2.1.0 (source: frontmatter and server release evidence) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v2.1.0:state.json\n\n{\r\n  \"History\": [\r\n    {\r\n      \"Time\": \"2026-05-26 18:16:11\",\r\n      \"Genre\": \"jazz\",\r\n      \"Name\": \"1940s Radio Station\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8082/stream\",\r\n      \"Duration\": \"00:06:06\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 11:28:50\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"1940s Radio Station\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8082/stream\",\r\n      \"Duration\": null,\r\n      \"Note\": \"Mood: кантри\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 11:34:17\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Polymer Radio (Music supplied by the \\\"Free Music Archive\\\")\",\r\n      \"Url\": \"http://uk5.internet-radio.com:8185/stream\",\r\n      \"Duration\": \"00:00:16\",\r\n      \"Note\": \"Mood: кантри\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 11:34:34\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Ambient Radio .org - Deeply Beautiful Chillout Music - A Heavenly World of Sound\",\r\n      \"Url\": \"http://uk2.internet-radio.com:8171/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 11:36:02\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Radio Te Amo Mama Hilda\",\r\n      \"Url\": \"http://uk2.internet-radio.com:8028/stream\",\r\n      \"Duration\": null,\r\n      \"Note\": \"Mood: кантри\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-27 11:36:31\",\r\n      \"Genr\n\nArchive v2.0.0: 6 files, 13284 bytes\n\nFiles: _meta.json (146b), scripts/play_music.py (16733b), scripts/show_history.py (11760b), skill-card.md (2279b), SKILL.md (6973b), state.json (480b)","readmeExcerpt":"Skill: Internet Radio Music Player Owner: dynamicsalex Summary: Plays internet radio streams via Foobar2000 based on your mood, selecting a genre and stream from the Internet Radio Music DB with control and history support. Tags: foobar2000:2.0.0, internet-radio:2.0.0, latest:2.5.3, music:2.0.0, player:2.0.0, radio:2.0.0 Version history: v2.5.3 | 2026-06-05T11:50:06.082Z | auto - Removed the file: skill-card.md - No ","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"openclaw plugins install \"clawhub:internet-radio-music-webui\"\nopenclaw gateway restart"},{"language":"bash","snippet":"# 1. Install the stream database skill (required!)\nopenclaw skills install internet-radio-music-db\n\n# 2. Restart Gateway\nopenclaw gateway restart"},{"language":"text","snippet":"(genre_match_level, position, extra_genres, -speed)"},{"language":"bash","snippet":"openclaw plugins install \"clawhub:internet-radio-music-webui\"\nopenclaw gateway restart"},{"language":"bash","snippet":"# 1. Install the stream database skill (required!)\nopenclaw skills install internet-radio-music-db\n\n# 2. Restart Gateway\nopenclaw gateway restart"},{"language":"text","snippet":"(genre_match_level, position, extra_genres, -speed)"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: internet-radio-music-player\nversion: 2.5.0\ndescription: Internet radio stream player via Foobar2000. Smart 4-level relevance sorting by genre. Supports: play/stop/next/prev/resume, playback history with filters and export. Requires the Internet Radio Music DB skill. For the easiest management experience, use the internet-radio-music-webui plugin.\nsummary: Internet radio stream player via Foobar2000. Plays music by mood, selecting genre and stream from the Internet Radio Music DB with playback controls and history. Use the internet-radio-music-webui plugin for the simplest playback and DB management.\nmetadata:\n  openclaw:\n    requires:\n      bins:\n        - python3\n    emoji: \"🎶\"\n    homepage: https://clawhub.ai/skills/internet-radio-music-player\n---\n\n# Internet Radio Music Player\n\n**⚠️ WARNING: This skill REQUIRES the Internet Radio Music DB skill to work!**\n\nWithout the stream database skill installed, playback is impossible.\n\n## 🌐 WebUI Plugin (Recommended)\n\n**The easiest way to manage playback and the stream database is the [internet-radio-music-webui](https://clawhub.ai/dynamicsAlex/internet-radio-music-webui) plugin.**\n\nThe plugin provides an embeddable web panel with:\n- **Playback controls**: Play, Stop, Next, Previous, Resume (auto-resume after stop)\n- **Mood-based genre selector**: Pick from 20+ genres via dropdown\n- **Stream database management**: View stats (genres, languages, efficiency), list streams, check availability, rebuild database — all from the browser\n- **WebChat integration**: Embed directly in webchat with `[embed url=\"http://127.0.0.1:18789/mplayer\"]`\n\n**Install the plugin:**\n```bash\nopenclaw plugins install \"clawhub:internet-radio-music-webui\"\nopenclaw gateway restart\n```\n\nThe plugin auto-detects `play_music.py` and the database scripts from this skill and the Internet Radio Music DB skill.\n\n## Install dependencies\n\n```bash\n# 1. Install the stream database skill (required!)\nopenclaw skills install internet-radio-music-db\n\n# 2. Restart Gateway\nopenclaw gateway restart\n```\n\n## How it works\n\n1. User specifies a mood (e.g. \"play happy music\")\n2. Skill determines suitable genres from the mood map\n3. **Streams are fetched from the Internet Radio Music DB** (`~/.openclaw/skills/internet-radio-music-db/state.json`)\n4. Streams are sorted by relevance to the requested genre (see algorithm below)\n5. Stream availability is checked (HTTP request)\n6. Foobar2000 is launched with the found URL\n7. History is saved to `state.json`\n\n## Stream selection algorithm\n\nWhen selecting a stream from the database, a 4-level relevance sorting is applied:\n\n### 1. Primary `genre` match (highest priority)\n\nStreams with an exact `genre` match (database field) are always ranked higher than those matched only via the `genres` list.\n\n### 2. Genre position in `genres` field\n\nThe requested genre is searched in the stream's `genres` list. The **closer to the beginning** — the higher the priority. If `genre` matches exactly and `genres` is empty — p"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn775k2zzav7y8rpwwm218x0b587f0hj\",\n  \"slug\": \"internet-radio-music-player\",\n  \"version\": \"2.5.3\",\n  \"publishedAt\": 1780660206082\n}"},{"path":"skill-card.md","content":"## Description:\n\nPlays internet radio streams via Foobar2000 by mapping mood or genre requests to stations from the Internet Radio Music DB, with playback controls and history support.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[dynamicsalex](https://clawhub.ai/user/dynamicsalex)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to control internet radio playback from an agent, including mood-based station selection, playback controls, status checks, and listening history review.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill opens external stream URLs and performs outbound stream checks.\n\nMitigation: Install only in environments where outbound radio stream access is acceptable, and prefer explicit radio-specific requests to reduce accidental activation.\n\nRisk: The skill can control and force-stop local Foobar2000 processes.\n\nMitigation: Use it on systems where agent-driven Foobar2000 control is expected, and avoid running it during unrelated manual Foobar2000 sessions.\n\nRisk: Playback history exports can include stream metadata in HTML or CSV formats.\n\nMitigation: Sanitize exported history before opening files that contain untrusted stream metadata.\n\n## Reference(s):\n\n- [ClawHub Skill Page](https://clawhub.ai/dynamicsalex/skills/internet-radio-music-player)\n- [Internet Radio Music WebUI Plugin](https://clawhub.ai/dynamicsAlex/internet-radio-music-webui)\n\n## Skill Output:\n\n**Output Type(s):** [text, shell commands, configuration, files]\n\n**Output Format:** [Plain text command output with optional CSV, HTML, or JSON history exports.]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Requires Python 3, Foobar2000, and the Internet Radio Music DB skill.]\n\n## Skill Version(s):\n\n2.5.3 (source: server release evidence; artifact frontmatter says 2.5.0)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."},{"path":"state.json","content":"{\r\n  \"History\": [\r\n    {\r\n      \"Time\": \"2026-05-28 20:23:11\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"01:25:03\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-28 21:48:17\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Spirit Country Radio\",\r\n      \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n      \"Duration\": \"00:44:06\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-28 22:43:31\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": null\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 09:14:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Spirit Country Radio\",\r\n      \"Url\": \"http://us2.internet-radio.com:8035/stream\",\r\n      \"Duration\": \"00:04:16\",\r\n      \"Note\": \"Mood: country\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 09:18:43\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"01:27:13\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 10:45:59\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"All Country Radio\",\r\n      \"Url\": \"http://uk3.internet-radio.com:8024/stream\",\r\n      \"Duration\": \"00:19:22\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:05:24\",\r\n      \"Genre\": \"country\",\r\n      \"Name\": \"Y Country - Today's Best Country\",\r\n      \"Url\": \"http://us5.internet-radio.com:8125/stream\",\r\n      \"Duration\": \"00:36:58\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:36\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:03\",\r\n      \"Note\": \"Mood: ambient\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:43\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:04\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:42:50\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:19\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:12\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:10\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:25\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"Duration\": \"00:00:10\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:38\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"Brown Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8280/stream\",\r\n      \"Duration\": \"00:00:08\"\r\n    },\r\n    {\r\n      \"Time\": \"2026-05-29 11:43:49\",\r\n      \"Genre\": \"ambient\",\r\n      \"Name\": \"White Noise Radio\",\r\n      \"Url\": \"http://uk1.internet-radio.com:8267/stream\",\r\n      \"D"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1635,"uniquenessScore":39,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T07:30:40.191Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T07:30:40.191Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T10:52:47.851Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}