diff --git a/.opencode/plans/dap-step-commands-simplification.md b/.opencode/plans/dap-step-commands-simplification.md index b412856f8..6b644b545 100644 --- a/.opencode/plans/dap-step-commands-simplification.md +++ b/.opencode/plans/dap-step-commands-simplification.md @@ -1,6 +1,6 @@ # Plan: Simplify Step Commands to Use REPL Format -**Status:** Ready for Implementation +**Status:** Complete **Date:** January 2026 **Prerequisites:** dap-step-manipulation.md (Chunks 1-9 completed) @@ -30,12 +30,12 @@ This causes issues: ## Progress Checklist -- [ ] **Chunk 1:** Update StepCommandParser - `steps` prefix, `--output` flag, remove JSON parsing -- [ ] **Chunk 2:** Update StepCommandHandler - format responses based on OutputFormat -- [ ] **Chunk 3:** Update Browser Extension - build REPL command strings -- [ ] **Chunk 4:** Update REPL context detection in browser extension -- [ ] **Chunk 5:** Update/remove tests -- [ ] **Chunk 6:** Update plan documentation +- [x] **Chunk 1:** Update StepCommandParser - `steps` prefix, `--output` flag, remove JSON parsing +- [x] **Chunk 2:** Update StepCommandHandler - format responses based on OutputFormat +- [x] **Chunk 3:** Update Browser Extension - build REPL command strings +- [x] **Chunk 4:** Update REPL context detection in browser extension +- [x] **Chunk 5:** Update/remove tests +- [x] **Chunk 6:** Update plan documentation --- diff --git a/.opencode/plans/dap-step-manipulation.md b/.opencode/plans/dap-step-manipulation.md index 7188a2e6e..2a1bdb597 100644 --- a/.opencode/plans/dap-step-manipulation.md +++ b/.opencode/plans/dap-step-manipulation.md @@ -11,10 +11,10 @@ - [x] **Chunk 2:** Step Serializer (ActionStep → YAML) - [x] **Chunk 3:** Step Factory (Create new steps) - [x] **Chunk 4:** Step Manipulator (Queue operations) -- [x] **Chunk 5:** REPL Commands (!step list, !step add run, !step edit, !step remove, !step move) -- [x] **Chunk 6:** Action Download Integration (!step add uses) -- [x] **Chunk 7:** Export Command (!step export) -- [x] **Chunk 8:** JSON API for Browser Extension +- [x] **Chunk 5:** REPL Commands (steps list, steps add run, steps edit, steps remove, steps move) +- [x] **Chunk 6:** Action Download Integration (steps add uses) +- [x] **Chunk 7:** Export Command (steps export) +- [x] **Chunk 8:** Output Format Flag (--output text|json for programmatic use) - [x] **Chunk 9:** Browser Extension UI ## Overview @@ -28,7 +28,7 @@ This transforms the debugger from a "read-only inspection tool" into an **intera - **Primary:** Enable add/edit/move/delete of job steps during debug session - **Primary:** Support both `run` and `uses` step types - **Primary:** Export modified steps as valid YAML -- **Secondary:** Provide both REPL commands and JSON API for different clients +- **Secondary:** Provide `--output` flag for text/JSON response format - **Non-goal:** Full workflow file reconstruction (steps section only) - **Non-goal:** Production action restriction enforcement (noted for later) @@ -37,9 +37,17 @@ This transforms the debugger from a "read-only inspection tool" into an **intera ### Grammar ``` -!step [target] [options] +steps [target] [options] [--output text|json] ``` +### Output Format + +All commands support the `--output` flag to control response format: +- `--output text` (default) - Human-readable text output +- `--output json` - JSON output for programmatic use +- Short form: `-o json`, `-o text` +- Equals form: `--output=json`, `--output=text` + ### Index Reference - **1-based indexing** for user-friendliness @@ -50,16 +58,16 @@ This transforms the debugger from a "read-only inspection tool" into an **intera | Command | Purpose | Example | |---------|---------|---------| -| `!step list` | Show all steps | `!step list --verbose` | -| `!step add` | Add new step | `!step add run "npm test" --after 3` | -| `!step edit` | Modify step | `!step edit 4 --script "npm run test:ci"` | -| `!step remove` | Delete step | `!step remove 5` | -| `!step move` | Reorder step | `!step move 5 --after 2` | -| `!step export` | Generate YAML | `!step export --with-comments` | +| `steps list` | Show all steps | `steps list --verbose` | +| `steps add` | Add new step | `steps add run "npm test" --after 3` | +| `steps edit` | Modify step | `steps edit 4 --script "npm run test:ci"` | +| `steps remove` | Delete step | `steps remove 5` | +| `steps move` | Reorder step | `steps move 5 --after 2` | +| `steps export` | Generate YAML | `steps export --with-comments` | ### Position Modifiers -For `!step add` and `!step move`: +For `steps add` and `steps move`: - `--at ` — Insert at specific position - `--after ` — Insert after step - `--before ` — Insert before step @@ -91,11 +99,16 @@ See "Command API Full Reference" section at end of document. ```csharp public interface IStepCommandParser { - StepCommand Parse(string input); // "!step add run \"echo hello\" --after 3" - bool IsStepCommand(string input); // Starts with "!step" or is JSON with cmd:"step.*" + StepCommand Parse(string input); // "steps add run \"echo hello\" --after 3" + bool IsStepCommand(string input); // Starts with "steps " or equals "steps" } - public abstract class StepCommand { } + public enum OutputFormat { Text, Json } + + public abstract class StepCommand + { + public OutputFormat Output { get; set; } = OutputFormat.Text; + } public class ListCommand : StepCommand { public bool Verbose; } public class AddRunCommand : StepCommand { public string Script; @@ -450,7 +463,7 @@ See "Command API Full Reference" section at end of document. ### Chunk 5: REPL Commands (run steps) -**Goal:** Implement `!step list`, `!step add run`, `!step edit`, `!step remove`, `!step move`. +**Goal:** Implement `steps list`, `steps add run`, `steps edit`, `steps remove`, `steps move`. **Files to modify:** - `src/Runner.Worker/Dap/DapDebugSession.cs` — Add `HandleStepCommandAsync()` @@ -557,9 +570,9 @@ See "Command API Full Reference" section at end of document. --- -### Chunk 6: Action Download Integration (!step add uses) +### Chunk 6: Action Download Integration (steps add uses) -**Goal:** Support `!step add uses` with full action download. +**Goal:** Support `steps add uses` with full action download. **Files to modify:** - `src/Runner.Worker/Dap/StepCommands/StepCommandHandler.cs` @@ -628,7 +641,7 @@ See "Command API Full Reference" section at end of document. --- -### Chunk 7: Export Command (!step export) +### Chunk 7: Export Command (steps export) **Goal:** Generate YAML output for modified steps. @@ -701,77 +714,93 @@ See "Command API Full Reference" section at end of document. --- -### Chunk 8: JSON API for Browser Extension +### Chunk 8: Output Format Flag for Browser Extension -**Goal:** Add JSON command support for programmatic access. +**Goal:** Add `--output` flag support for programmatic access (replaces separate JSON API). **Files to modify:** - `src/Runner.Worker/Dap/StepCommands/StepCommandParser.cs` -- `src/Runner.Worker/Dap/DapDebugSession.cs` +- `src/Runner.Worker/Dap/StepCommands/StepCommandHandler.cs` **Details:** -1. **Detect JSON input:** +1. **Add OutputFormat enum and property to base StepCommand:** ```csharp - public bool IsStepCommand(string input) + public enum OutputFormat { Text, Json } + + public abstract class StepCommand { - var trimmed = input.Trim(); - return trimmed.StartsWith("!step") || - (trimmed.StartsWith("{") && trimmed.Contains("\"cmd\"") && trimmed.Contains("\"step.")); + public OutputFormat Output { get; set; } = OutputFormat.Text; } ``` -2. **Parse JSON commands:** +2. **Parse `--output` flag in command parser:** ```csharp - public StepCommand Parse(string input) + // Recognize --output json, --output text, -o json, -o text, --output=json + private OutputFormat ParseOutputFlag(List tokens) { - var trimmed = input.Trim(); - if (trimmed.StartsWith("{")) - return ParseJsonCommand(trimmed); - else - return ParseReplCommand(trimmed); - } - - private StepCommand ParseJsonCommand(string json) - { - var obj = JObject.Parse(json); - var cmd = obj["cmd"]?.ToString(); - - return cmd switch + for (int i = 0; i < tokens.Count; i++) { - "step.list" => new ListCommand { Verbose = obj["verbose"]?.Value() ?? false }, - "step.add" => ParseJsonAddCommand(obj), - "step.edit" => ParseJsonEditCommand(obj), - "step.remove" => new RemoveCommand { Index = obj["index"].Value() }, - "step.move" => ParseJsonMoveCommand(obj), - "step.export" => new ExportCommand { - ChangesOnly = obj["changesOnly"]?.Value() ?? false, - WithComments = obj["withComments"]?.Value() ?? false - }, - _ => throw new StepCommandException($"Unknown command: {cmd}") + var token = tokens[i].ToLower(); + if (token == "--output" || token == "-o") + { + if (i + 1 < tokens.Count) + { + var format = tokens[i + 1].ToLower(); + tokens.RemoveAt(i); tokens.RemoveAt(i); + return format == "json" ? OutputFormat.Json : OutputFormat.Text; + } + } + else if (token.StartsWith("--output=")) + { + var format = token.Substring("--output=".Length); + tokens.RemoveAt(i); + return format == "json" ? OutputFormat.Json : OutputFormat.Text; + } + } + return OutputFormat.Text; + } + ``` + +3. **Format responses based on Output property in handler:** + ```csharp + if (command.Output == OutputFormat.Json) + { + return new StepCommandResult + { + Success = true, + Message = JsonConvert.SerializeObject(new { Success = true, Result = data }) + }; + } + else + { + return new StepCommandResult + { + Success = true, + Message = FormatAsText(data) }; } ``` -3. **JSON response format:** - ```csharp - // For JSON input, return structured JSON response - if (wasJsonInput) - { - return CreateSuccessResponse(new EvaluateResponseBody - { - Result = JsonConvert.SerializeObject(result), - Type = "json" - }); - } +4. **Browser extension sends REPL commands with `--output json`:** + ```javascript + // Browser extension builds command strings like: + // "steps list --output json" + // "steps add run \"echo test\" --after 3 --output json" ``` -**Testing:** -- All commands via JSON -- Verify JSON responses are parseable -- Test error responses +**Benefits over separate JSON API:** +- Single code path for parsing all commands +- Easier debugging (UI sends same commands humans would type) +- Commands can be copy-pasted from UI to console for testing +- Less code to maintain -**Estimated effort:** Small-medium +**Testing:** +- All commands with `--output json` return valid JSON +- All commands with `--output text` (or default) return human-readable text +- Short form `-o json` works correctly + +**Estimated effort:** Small --- @@ -845,13 +874,18 @@ See "Command API Full Reference" section at end of document. } ``` -6. **Send commands via JSON API:** +6. **Send commands via REPL format with `--output json`:** ```javascript async function addStep(type, options) { - const cmd = { cmd: 'step.add', type, ...options }; - const response = await sendEvaluate(JSON.stringify(cmd)); + const cmd = buildStepCommand('step.add', { type, ...options }); + const response = await sendEvaluate(cmd); // e.g., "steps add run \"echo test\" --output json" refreshStepList(); } + + async function loadSteps() { + const response = await sendEvaluate('steps list --output json'); + // Parse JSON response + } ``` **Testing:** @@ -883,7 +917,9 @@ See "Command API Full Reference" section at end of document. | File | Chunk | Changes | |------|-------|---------| | `DapDebugSession.cs` | 1, 5 | Add command dispatch, wire up services | -| `content.js` | 9 | Steps panel, dialogs, export modal | +| `StepCommandParser.cs` | 8 | Add `--output` flag parsing | +| `StepCommandHandler.cs` | 8 | Format responses based on OutputFormat | +| `content.js` | 9 | Steps panel, dialogs, export modal, build REPL commands | | `content.css` | 9 | Styling for new UI elements | | `background.js` | 9 | Helper functions if needed | @@ -891,10 +927,23 @@ See "Command API Full Reference" section at end of document. ## Command API Full Reference -### !step list +### Output Format Flag + +All commands support the `--output` flag: ``` -!step list [--verbose] +steps ... --output text # Human-readable output (default) +steps ... --output json # JSON output for programmatic use +steps ... -o json # Short form +steps ... --output=json # Equals form +``` + +The browser extension uses `--output json` for all commands to receive structured responses. + +### steps list + +``` +steps list [--verbose] [--output text|json] ``` Show all steps with their indices, status, and modification state. @@ -912,16 +961,25 @@ Steps: Legend: ✓ = completed, ▶ = current/paused, [ADDED] = new, [MODIFIED] = edited ``` -**JSON:** +**JSON output (`steps list --output json`):** ```json -{"cmd": "step.list", "verbose": false} +{ + "Success": true, + "Result": [ + {"index": 1, "name": "Checkout", "type": "uses", "typeDetail": "actions/checkout@v4", "status": "completed"}, + {"index": 2, "name": "Setup Node", "type": "uses", "typeDetail": "actions/setup-node@v4", "status": "completed"}, + {"index": 3, "name": "Install deps", "type": "run", "typeDetail": "npm ci", "status": "current"}, + {"index": 4, "name": "Run tests", "type": "run", "typeDetail": "npm test", "status": "pending", "change": "MODIFIED"}, + {"index": 5, "name": "Build", "type": "run", "typeDetail": "npm run build", "status": "pending", "change": "ADDED"} + ] +} ``` -### !step add +### steps add **Run step:** ``` -!step add run "