Skip to content

Commit d620b13

Browse files
committed
feat: implement story 6.2 and add get_track_details tool
1 parent 3bf8664 commit d620b13

11 files changed

Lines changed: 649 additions & 42 deletions

File tree

.github/prompts/bmad-dev-agent.prompt.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

.github/prompts/bmad-orchestrator-agent.prompt.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

.github/prompts/bmad-sm-agent.prompt.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

docs/api-reference.md

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ Communication is message-based, typically using JSON-RPC or a similar structured
171171
* `DEVICE_NOT_SELECTED`
172172
* `INVALID_PARAMETER_INDEX`
173173
* `INVALID_PARAMETER` (for value out of range)
174-
* `BITWIG_ERROR`
174+
* `BITWIG_API_ERROR`
175175

176176
#### `set_selected_device_parameters`
177177
* **Description**: Set multiple parameter values (by index 0-7) of the user-selected device in Bitwig simultaneously.
@@ -206,7 +206,7 @@ Communication is message-based, typically using JSON-RPC or a similar structured
206206
```
207207
* **Errors**:
208208
* Top-level: `DEVICE_NOT_SELECTED`, `INVALID_PARAMETER` (for overall payload issues)
209-
* Per-item in `results`: `INVALID_PARAMETER_INDEX`, `INVALID_PARAMETER`, `BITWIG_ERROR`
209+
* Per-item in `results`: `INVALID_PARAMETER_INDEX`, `INVALID_PARAMETER`, `BITWIG_API_ERROR`
210210

211211
### Session Control Commands
212212

@@ -235,7 +235,7 @@ Communication is message-based, typically using JSON-RPC or a similar structured
235235
* `INVALID_ARGUMENT`: Missing or invalid parameters (e.g., empty track_name, negative clip_index)
236236
* `TRACK_NOT_FOUND`: The specified track name was not found
237237
* `CLIP_INDEX_OUT_OF_BOUNDS`: The clip index is outside the valid range for the track
238-
* `BITWIG_ERROR`: Internal error occurred while launching clip
238+
* `BITWIG_API_ERROR`: Internal error occurred while launching clip
239239

240240
#### `session_launchSceneByIndex`
241241
* **Description**: Launch an entire scene in Bitwig by providing its numerical index.
@@ -258,7 +258,7 @@ Communication is message-based, typically using JSON-RPC or a similar structured
258258
```
259259
* **Errors**:
260260
* `SCENE_NOT_FOUND`
261-
* `BITWIG_ERROR`
261+
* `BITWIG_API_ERROR`
262262

263263
#### `session_launchSceneByName`
264264
* **Description**: Launch an entire scene in Bitwig by providing its name.
@@ -282,7 +282,7 @@ Communication is message-based, typically using JSON-RPC or a similar structured
282282
```
283283
* **Errors**:
284284
* `SCENE_NOT_FOUND`
285-
* `BITWIG_ERROR`
285+
* `BITWIG_API_ERROR`
286286

287287
### Track Information Commands
288288

@@ -355,9 +355,85 @@ Communication is message-based, typically using JSON-RPC or a similar structured
355355
- `devices[].type`: Type of the device ("Instrument", "AudioFX", "NoteFX")
356356
* **Errors**:
357357
* `INVALID_PARAMETER`: Invalid track type filter
358-
* `BITWIG_ERROR`: Internal error occurred while retrieving tracks
358+
* `BITWIG_API_ERROR`: Internal error occurred while retrieving tracks
359359

360-
*(Further commands related to track manipulation, clip launching, device control, etc., will be detailed here as they are defined and implemented.)*
360+
#### `get_track_details`
361+
* **Description**: Retrieve detailed information for a specific track by index, name, or the currently selected track.
362+
* **Parameters**:
363+
```json
364+
{
365+
"track_index": 3,
366+
"track_name": "Drums",
367+
"get_selected": true
368+
}
369+
```
370+
Rules:
371+
- Exactly one of `track_index`, `track_name`, or `get_selected` may be provided. If none provided, behaves as `get_selected=true`.
372+
- Providing multiple results in `INVALID_PARAMETER`.
373+
- `track_name` match is case-sensitive.
374+
* **Returns**:
375+
```json
376+
{
377+
"status": "success",
378+
"data": {
379+
"index": 0,
380+
"name": "Drums",
381+
"type": "audio",
382+
"is_group": false,
383+
"parent_group_index": null,
384+
"activated": true,
385+
"color": "rgb(255,128,0)",
386+
"is_selected": true,
387+
"devices": [
388+
{ "index": 0, "name": "EQ Eight", "type": "AudioFX", "bypassed": false },
389+
{ "index": 1, "name": "Compressor", "type": "AudioFX", "bypassed": false }
390+
],
391+
"volume": 0.63,
392+
"volume_str": "-4.0 dB",
393+
"pan": 0.5,
394+
"pan_str": "C",
395+
"muted": false,
396+
"soloed": false,
397+
"armed": false,
398+
"monitor_enabled": true,
399+
"auto_monitor_enabled": false,
400+
"sends": [
401+
{ "name": "A", "volume": 0.4, "volume_str": "-8.0 dB", "activated": true },
402+
{ "name": "B", "volume": 0.0, "volume_str": "-inf", "activated": false }
403+
],
404+
"clips": [
405+
{
406+
"slot_index": 0,
407+
"scene_name": "Intro",
408+
"has_content": true,
409+
"clip_name": "Beat 1",
410+
"clip_color": "rgb(255,128,0)",
411+
"is_playing": false,
412+
"is_recording": false,
413+
"is_playback_queued": false
414+
},
415+
{
416+
"slot_index": 1,
417+
"scene_name": "Verse 1",
418+
"has_content": false,
419+
"clip_name": null,
420+
"clip_color": null,
421+
"is_playing": null,
422+
"is_recording": null,
423+
"is_playback_queued": null
424+
}
425+
]
426+
}
427+
}
428+
```
429+
* **Notes**:
430+
- Uses the same track index semantics and device summary format as `list_tracks`.
431+
- Color values are returned as RGB strings (e.g., `rgb(255,128,0)`).
432+
- Clip slot provides clip name and state flags; clip length and loop status are not exposed via slot API and are omitted.
433+
* **Errors**:
434+
* `INVALID_PARAMETER`: Invalid combination or types of parameters
435+
* `TRACK_NOT_FOUND`: Target track not found or no track selected when required
436+
* `BITWIG_API_ERROR`: Internal Bitwig API error
361437

362438
### Error Handling
363439

docs/stories/6.2.story.md

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
**User Story:**
66

7-
* As an AI agent, I want to get detailed information for a specific track (by index, name, or by targeting the currently selected track, defaulting to selected if no specifier), including its parameters (volume, pan, mute, solo, arm), sends, and a list of its clips with their properties (name, color, length, loop status), so I can perform targeted analysis or suggest modifications.
7+
* As an AI agent, I want to get detailed information for a specific track (by index, name, or by targeting the currently selected track, defaulting to selected if no specifier), including its parameters (volume, pan, mute, solo, arm), sends, and a list of its clips with their properties (name, color, playback state), so I can perform targeted analysis or suggest modifications.
88

99
**Acceptance Criteria:**
1010

@@ -13,6 +13,11 @@
1313
* `track_index` (integer, optional): 0-based index of the track.
1414
* `track_name` (string, optional): Name of the track.
1515
* `get_selected` (boolean, optional): If true, retrieves details for the currently selected track. If no parameters (`track_index`, `track_name`, `get_selected`) are provided, this defaults to `true`.
16+
* **Parameter Rules:**
17+
* Exactly one of `track_index`, `track_name`, or `get_selected` may be provided. Supplying more than one results in an `INVALID_PARAMETER` error.
18+
* If none are provided, the tool behaves as if `get_selected=true`.
19+
* `track_name` matching is case-sensitive (consistent with `launch_clip`).
20+
* `index` refers to the project’s main 0-based track index, consistent with `list_tracks`.
1621
* **Response Body:** A single track object containing:
1722
* All fields from the `list_tracks` response object for this track (i.e., `index`, `name`, `type`, `is_group`, `parent_group_index`, `activated`, `color`, `is_selected`, and the `devices` array with device summaries).
1823
* `volume` (float): Normalized volume (0.0-1.0).
@@ -23,7 +28,7 @@
2328
* `soloed` (boolean): Is the track soloed.
2429
* `armed` (boolean): Is the track armed for recording.
2530
* `monitor_enabled` (boolean): Is monitoring enabled.
26-
* `auto_monitor_enabled` (boolean): Is auto-monitoring enabled.
31+
* `auto_monitor_enabled` (boolean): Whether auto-monitor mode is active (derived via monitorMode).
2732
* `sends` (array of objects): List of sends for the track.
2833
* `name` (string): Name of the send channel.
2934
* `volume` (float): Normalized send level.
@@ -33,31 +38,36 @@
3338
* `slot_index` (integer): 0-based index of the clip slot.
3439
* `scene_name` (string, nullable): Name of the scene this slot aligns with.
3540
* `has_content` (boolean): True if the slot contains a clip.
36-
* `clip_name` (string, nullable): Name of the clip.
37-
* `clip_color` (string, nullable): Color of the clip.
38-
* `length` (string, nullable): Length of the clip (e.g., "4.0.0").
39-
* `is_looping` (boolean, nullable): True if the clip is set to loop.
41+
* `clip_name` (string, nullable): Clip name from `ClipLauncherSlot.name()` (null if empty or unavailable).
42+
* `clip_color` (string, nullable): Color of the clip in RGB string format (e.g., "rgb(255,128,0)").
43+
* `is_playing` (boolean, nullable): True if the clip in this slot is currently playing.
44+
* `is_recording` (boolean, nullable): True if the clip in this slot is currently recording.
45+
* `is_playback_queued` (boolean, nullable): True if playback is queued for the clip in this slot.
4046
* The `get_track_details` tool correctly identifies the target track based on `track_index`, `track_name`, or `get_selected` (or defaults to selected).
4147
* The tool retrieves all specified detailed information using the Bitwig API (e.g., `CursorTrack` or specific `Track` object properties, `ClipLauncherSlotBank`).
42-
* The tool correctly formats clip `length` and `is_looping` status.
48+
* The tool exposes available clip state and scene data; clip length and loop status are intentionally omitted (not exposed by slot API).
4349
* The tool handles cases where a track is not found (for by index/name) or no track is selected (if `get_selected` is true or defaulted) by returning an appropriate error response.
44-
* The `api-reference.md` is updated with the `get_track_details` tool specification.
50+
* **Error Responses:**
51+
* `INVALID_PARAMETER` for invalid combinations or types of parameters.
52+
* `TRACK_NOT_FOUND` if the target track cannot be resolved (including the case when `get_selected` is used but no track is selected).
53+
* `BITWIG_API_ERROR` for Bitwig API failures.
54+
* The `api-reference.md` is updated with the `get_track_details` tool specification and notes on clip field limitations.
4555
* Unit tests are written for the `GetTrackDetailsTool.java` logic.
4656
* Manual testing confirms accuracy against various Bitwig project configurations and track states.
4757

4858
**Tasks:**
4959

50-
1. Create `GetTrackDetailsTool.java` implementing the `MCPTool` interface.
60+
1. Create `GetTrackDetailsTool.java` following the existing static specification pattern (e.g., `ListTracksTool.specification(...)`) and using the unified `McpErrorHandler` error handling.
5161
2. Implement logic to identify the target track:
5262
* If `track_index` is provided, get track by index.
53-
* If `track_name` is provided, find track by name.
63+
* If `track_name` is provided, find track by name (case-sensitive).
5464
* If `get_selected` is true, or if no parameters are provided, use `CursorTrack`.
5565
3. Once the target track is identified, retrieve all basic information as per `list_tracks` (or reuse logic).
5666
4. Retrieve detailed properties: `volume`, `pan`, `muted`, `soloed`, `armed`, `monitor_enabled`, `auto_monitor_enabled`.
5767
5. Retrieve send information.
58-
6. Access the track's `ClipLauncherSlotBank` to retrieve details for each clip slot: `slot_index`, `scene_name`, `has_content`, `clip_name`, `clip_color`, `length`, `is_looping`.
68+
6. Access the track's `ClipLauncherSlotBank` to retrieve details for each clip slot: `slot_index`, `scene_name`, `has_content`, `clip_name`, color, and playback/record/queue state flags.
5969
7. Construct the JSON response as specified.
60-
8. Implement robust error handling (e.g., track not found, no track selected).
61-
9. Update `docs/api-reference.md` with the `get_track_details` tool details.
62-
10. Write JUnit tests for `GetTrackDetailsTool.java`.
70+
8. Implement robust error handling (e.g., invalid parameter combinations, track not found, no track selected).
71+
9. Update `docs/api-reference.md` with the `get_track_details` tool details and examples, including notes on clip field limitations.
72+
10. Write JUnit tests for `GetTrackDetailsTool.java` (cover all parameter paths, formatting, and empty states).
6373
11. Perform manual integration testing.

src/main/java/io/github/fabb/wigai/WigAIExtension.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ private void startServer() {
7171
try {
7272
// Create MCP servlet from the MCP server manager
7373
ServletHolder mcpServlet = mcpServerManager.createMcpServlet(MCP_ENDPOINT_PATH);
74-
74+
7575
// Start Jetty server with the MCP servlet
7676
jettyServerManager.startServer(mcpServlet, MCP_ENDPOINT_PATH);
7777
} catch (Exception e) {
@@ -91,7 +91,7 @@ private void restartServer() {
9191
try {
9292
// Create MCP servlet from the MCP server manager
9393
ServletHolder mcpServlet = mcpServerManager.createMcpServlet(MCP_ENDPOINT_PATH);
94-
94+
9595
// Restart Jetty server with the MCP servlet
9696
jettyServerManager.restartServer(mcpServlet, MCP_ENDPOINT_PATH);
9797
} catch (Exception e) {

0 commit comments

Comments
 (0)