Skip to content

Conversation

@bmerkle
Copy link
Contributor

@bmerkle bmerkle commented Feb 3, 2026

  • implemented a local Player
  • there are currently problems with spotify to get a developer API key and application, hence here is a local Player basic implementation as alternative

…n (based on V2 behaviour)

- enhanced calendar client login with better authentication and error handling
- fixed some arguments (e.g. passing of dates/search strings(
- there are currently problems with spotify to get a developer API key and application, hence here is a local Player basic implementation as alternative
Copilot AI review requested due to automatic review settings February 3, 2026 23:44
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request implements a local music player agent as an alternative to Spotify, which the PR description indicates has become difficult to access for developer API keys. The implementation provides basic music playback functionality using platform-native audio players (PowerShell/Windows Media Player on Windows, afplay on macOS, mpv on Linux).

Changes:

  • Added new playerLocal agent package with playback controls, queue management, and file browsing capabilities
  • Integrated the new agent into the defaultAgentProvider configuration
  • Unrelated: Substantially rewrote the calendar agent to integrate with Microsoft Graph API (not mentioned in PR description)

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 19 comments.

Show a summary per file
File Description
ts/pnpm-lock.yaml Added dependencies for the new playerLocal package including play-sound, chalk, debug, and dotenv
ts/packages/defaultAgentProvider/package.json Added music-local workspace dependency
ts/packages/defaultAgentProvider/data/config.json Registered localPlayer agent with name "music-local"
ts/packages/agents/playerLocal/package.json Package definition for the new local player agent
ts/packages/agents/playerLocal/src/tsconfig.json TypeScript configuration for the playerLocal package
ts/packages/agents/playerLocal/src/localPlayerService.ts Core service implementing local audio file playback using platform-specific commands
ts/packages/agents/playerLocal/src/agent/localPlayerSchema.ts TypeScript type definitions for player actions
ts/packages/agents/playerLocal/src/agent/localPlayerSchema.json Schema metadata configuration
ts/packages/agents/playerLocal/src/agent/localPlayerSchema.agr Grammar rules for natural language command parsing (limited coverage)
ts/packages/agents/playerLocal/src/agent/localPlayerManifest.json Agent manifest with emoji and description
ts/packages/agents/playerLocal/src/agent/localPlayerHandlers.ts Action handlers for executing player commands
ts/packages/agents/playerLocal/src/agent/localPlayerCommands.ts Command-line interface handlers for the agent
ts/packages/agents/playerLocal/README.md Documentation for setup and usage
ts/packages/agents/calendar/src/calendarActionHandlerV3.ts Complete rewrite from stub to Graph API integration (unrelated to PR)
ts/packages/agents/agentUtils/graphUtils/src/graphClient.ts Authentication handling improvements for Graph API (unrelated to PR)
ts/packages/agents/agentUtils/graphUtils/src/calendarClient.ts Silent login support for calendar client (unrelated to PR)
Files not reviewed (1)
  • ts/pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@robgruen
Copy link
Collaborator

robgruen commented Feb 5, 2026

The calendar PR is in which is now causing some conflicts. Can you please resolve them and then I will review this PR.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
- layout fixes
- build, prettier, test run fine now
…stead of async fs.promises.mkdir without await. This fixes the race condition causing "ENOENT: no such file or directory" errors when tests try to write files immediately after creating directories.

grammarIntegration.spec.ts:

Added describeIf and hasTestKeys imports from test-lib
Wrapped the "Grammar Generation via populateCache" describe block with describeIf(..., () => hasTestKeys(), ...) to skip API-dependent tests when no API keys are configured
Increased the timeout from 60 seconds to 180 seconds (3 minutes) for the API call test, as LLM calls can be slow
Added test-lib to package.json devDependencies
@bmerkle
Copy link
Contributor Author

bmerkle commented Feb 7, 2026

@robgruen I have fixed conflicts and the code so it should work now.
I also had to fix some dependency problems and some tests were failing.
AFAIK the last two had nothing to do with my changes but i fixed them anyway in this PR.

I ran everything local (build, prettier, test) and also merged in main so it should be ok now.

Please have a look, it should be fine now

@robgruen
Copy link
Collaborator

robgruen commented Feb 9, 2026

@robgruen I have fixed conflicts and the code so it should work now. I also had to fix some dependency problems and some tests were failing. AFAIK the last two had nothing to do with my changes but i fixed them anyway in this PR.

I ran everything local (build, prettier, test) and also merged in main so it should be ok now.

Please have a look, it should be fine now

Thanks for doing that, it's appreciated! Will take a look.

}

public getMusicFolder(): string {
return this.musicFolder;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we store the updated music folder location to a settings file so that the user doesn't have to change it every time?

See the list agent for an example of how to write to local session storage: https://github.com/bmerkle/TypeAgent/blob/localPlayer/ts/packages/agents/list/src/listActionHandler.ts

return { ...this.state };
}

public listFiles(folderPath?: string): Track[] {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If users are like me and have the files organized by folder this won't work since you're not searching folders recursively:

Image

Comment on lines +61 to +62
@ <SetVolume> = set volume (to)? $(n:number) (percent)?
-> { actionName: "setVolume", parameters: { level: $(n) } }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have the desktop agent active these two actions can collide:

Image

I would maybe put "local Player" or something like that in grammer to disambiguate desktop vs. player commands. I think the desktop agent has precedence because is has more actions.

};
}

// Mute audio
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mute and UnMute could just be one action:

export interface MuteAction {
actionName: "mute";
parameters: {
isMuted: boolean; // true for yes, false for no
}
}

If you can collapse actions like this it's better as things scale because the LLM has less to choose from and can make this action decision as part of it's chain of thought process and doesn't consume additional attention heads.

return await this.playTrack(this.state.queue[prevIndex]);
}

public setVolume(level: number): boolean {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably output on non-windows machines that this command doesn't work.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for changeVolume


if (process.platform === "win32") {
// Use Windows Media Player via PowerShell
this.playerProcess = spawn(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After copying some files into the music folder and restarting I was able to get it to think it was playing some tracks:

Image

Windows Media Player never started.

Could you not just use the associated media player and then start that and then find that process so you could "pause" it?

@@ -0,0 +1,135 @@
# Local Music Player TypeAgent

A TypeAgent for playing local audio files without requiring any external service like Spotify.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would indicate that the actions in here might collide with the "player" agent and that it's recommended to have one or the other, not both and if you do, you should probably in your intent describe the one you want otherwise you may get the other one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants