feat: add SOUNDCLAW jukebox skill integration (#67)
Add the office jukebox flow so Spotify can be controlled from the SOUNDCLAW skill, manual jukebox UI, and local browser auth bridge during development. Made-with: Cursor
This commit is contained in:
@@ -140,6 +140,53 @@ const TODO_BOARD_EXAMPLE_JSON = `{
|
||||
}
|
||||
`;
|
||||
|
||||
// Keep this string synchronized with assets/skills/soundclaw/SKILL.md.
|
||||
const SOUNDCLAW_SKILL_MD = `---
|
||||
name: soundclaw
|
||||
description: Control Spotify playback, search music, and return shareable music links.
|
||||
metadata: {"openclaw":{"skillKey":"soundclaw"}}
|
||||
---
|
||||
|
||||
# SOUNDCLAW
|
||||
|
||||
Use this skill when the user wants an agent to search for music, play a song or playlist, control Spotify playback, or send back a shareable Spotify link on the same channel the request came from.
|
||||
|
||||
## Trigger
|
||||
|
||||
\`\`\`json
|
||||
{
|
||||
"activation": {
|
||||
"anyPhrases": [
|
||||
"spotify",
|
||||
"play a song",
|
||||
"play this song",
|
||||
"play music",
|
||||
"play a playlist",
|
||||
"find a song",
|
||||
"queue this song",
|
||||
"music link"
|
||||
]
|
||||
},
|
||||
"movement": {
|
||||
"target": "jukebox",
|
||||
"skipIfAlreadyThere": true
|
||||
}
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
When this skill is activated, the agent should walk to the office jukebox before handling the request.
|
||||
|
||||
- Treat requests from Telegram or any other external surface as valid triggers when they ask for Spotify playback, search, queueing, or music-link sharing.
|
||||
- The physical behavior for this skill is: go to the jukebox, perform the music-selection workflow, then report the result.
|
||||
- If the agent is already at the jukebox, continue without adding extra movement narration.
|
||||
|
||||
## Channel behavior
|
||||
|
||||
- Reply on the same active channel or session that received the request.
|
||||
- If playback cannot start but a matching track, album, or playlist is found, send back the best Spotify link instead of failing silently.
|
||||
- If multiple matches are plausible, ask a clarifying question instead of guessing.
|
||||
`;
|
||||
|
||||
const PACKAGED_SKILL_FILES: Record<string, PackagedSkillFile[]> = {
|
||||
"todo-board": [
|
||||
{
|
||||
@@ -151,9 +198,17 @@ const PACKAGED_SKILL_FILES: Record<string, PackagedSkillFile[]> = {
|
||||
content: TODO_BOARD_EXAMPLE_JSON,
|
||||
},
|
||||
],
|
||||
soundclaw: [
|
||||
{
|
||||
relativePath: "SKILL.md",
|
||||
content: SOUNDCLAW_SKILL_MD,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const readPackagedSkillFiles = (packageId: string): PackagedSkillFile[] => {
|
||||
export const readPackagedSkillFiles = (
|
||||
packageId: string,
|
||||
): PackagedSkillFile[] => {
|
||||
const files = PACKAGED_SKILL_FILES[packageId];
|
||||
if (!files || files.length === 0) {
|
||||
throw new Error(`Packaged skill assets are missing: ${packageId}`);
|
||||
|
||||
Reference in New Issue
Block a user