native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #134 from onevcat/onevclaw/issue-109-send-wait-contract

docs: add wait semantics to send contract

authored by

Wei Wang and committed by
GitHub
fe6107df 4056d4e0

+98 -7
+5 -2
doc-onevcat/contracts/cli/input.md
··· 179 179 ### Grammar 180 180 181 181 ```bash 182 - prowl send [selector] [--no-enter] [--json] [<text>] 182 + prowl send [selector] [--no-enter] [--no-wait] [--timeout <seconds>] [--json] [<text>] 183 183 # or 184 - printf '...' | prowl send [selector] [--no-enter] [--json] 184 + printf '...' | prowl send [selector] [--no-enter] [--no-wait] [--timeout <seconds>] [--json] 185 185 ``` 186 186 187 187 ### Rules ··· 192 192 - Both provided simultaneously: `INVALID_ARGUMENT`. 193 193 - Neither provided (or empty stdin): `EMPTY_INPUT`. 194 194 - Default sends trailing Enter; `--no-enter` disables it. 195 + - Default waits for command completion (requires shell integration); `--no-wait` disables it and returns immediately after delivery. 196 + - `--timeout <seconds>` sets the maximum wait duration (default: 30, range: 1–300). Ignored when `--no-wait` is used. 197 + - If the wait times out: `WAIT_TIMEOUT`. 195 198 196 199 ## 5.5 `key` 197 200
+23 -3
doc-onevcat/contracts/cli/schema.md
··· 410 410 "data": { 411 411 "type": "object", 412 412 "additionalProperties": false, 413 - "required": ["target", "input", "created_tab"], 413 + "required": ["target", "input", "created_tab", "wait"], 414 414 "properties": { 415 415 "target": { "$ref": "#/$defs/resolvedTarget" }, 416 416 "input": { ··· 433 433 "trailing_enter_sent": { "type": "boolean" } 434 434 } 435 435 }, 436 - "created_tab": { "type": "boolean" } 436 + "created_tab": { "type": "boolean" }, 437 + "wait": { 438 + "oneOf": [ 439 + { "type": "null" }, 440 + { 441 + "type": "object", 442 + "additionalProperties": false, 443 + "required": ["exit_code", "duration_ms"], 444 + "properties": { 445 + "exit_code": { 446 + "type": ["integer", "null"] 447 + }, 448 + "duration_ms": { 449 + "type": "integer", 450 + "minimum": 0 451 + } 452 + } 453 + } 454 + ] 455 + } 437 456 } 438 457 } 439 458 } ··· 459 478 "TARGET_NOT_FOUND", 460 479 "TARGET_NOT_UNIQUE", 461 480 "EMPTY_INPUT", 462 - "SEND_FAILED" 481 + "SEND_FAILED", 482 + "WAIT_TIMEOUT" 463 483 ] 464 484 }, 465 485 "message": { "type": "string", "minLength": 1 },
+70 -2
doc-onevcat/contracts/cli/send.md
··· 25 25 - stdin text 26 26 - `--no-enter` 27 27 28 + ## Wait behavior 29 + 30 + By default, `send` waits for the delivered command to finish before returning. This relies on shell integration (OSC 133) to detect command completion. When the command finishes, the response includes exit code and duration. 31 + 32 + - `--no-wait`: return immediately after text delivery without waiting for completion. 33 + - `--timeout <seconds>`: maximum time to wait (default: 30, range: 1–300). Ignored when `--no-wait` is used. 34 + - If the terminal does not have shell integration enabled, the wait will time out and return `WAIT_TIMEOUT`. 35 + 28 36 ### Input source semantics 29 37 30 38 `data.input.source` is **inferred from where the accepted payload came from**. It is not a separate `--source` flag. ··· 72 80 "bytes": 10, 73 81 "trailing_enter_sent": true 74 82 }, 75 - "created_tab": false 83 + "created_tab": false, 84 + "wait": { 85 + "exit_code": 0, 86 + "duration_ms": 1234 87 + } 76 88 } 77 89 } 78 90 ``` ··· 124 136 - boolean 125 137 - `true` only when targeting a worktree that had no current tab and Prowl had to create one before sending. 126 138 139 + ## `data.wait` 140 + 141 + - object or `null` 142 + - `null` when `--no-wait` is used (fire-and-forget mode). 143 + - When present (default behavior), contains: 144 + - `exit_code`: integer or `null`. The command's exit code reported by shell integration (OSC 133;D). `null` if the shell did not report an exit code. 145 + - `duration_ms`: integer. Wall-clock time in milliseconds from text delivery to command completion. 146 + 127 147 ## Output invariants 128 148 129 149 - The payload must describe the **resolved pane** that received the text. ··· 153 173 - `TARGET_NOT_UNIQUE` 154 174 - `EMPTY_INPUT` 155 175 - `SEND_FAILED` 176 + - `WAIT_TIMEOUT` 156 177 157 178 ## Notes 158 179 159 180 - `send` is text delivery, not general key simulation. Control inputs such as `ctrl-c` belong to `key`. 160 181 - Returning byte and character counts gives scripts enough confirmation without leaking payload contents into logs. 161 182 - A future implementation may add optional debug echo flags, but v1 default JSON must stay redaction-friendly. 183 + - Wait behavior depends on shell integration (OSC 133). Without it, `onCommandFinished` never fires and the wait will time out. The `WAIT_TIMEOUT` error message should hint at this possible cause. 184 + - `--no-wait` combined with `--no-enter` is the purest "paste text" mode — no Enter, no waiting. 185 + - A future `--capture` flag may return the command's output text alongside `wait`, pending upstream support for reading semantic zone data via the Ghostty C API. 162 186 163 187 ## Example: stdin + `--no-enter` 164 188 ··· 194 218 "bytes": 24, 195 219 "trailing_enter_sent": false 196 220 }, 197 - "created_tab": false 221 + "created_tab": false, 222 + "wait": { 223 + "exit_code": 0, 224 + "duration_ms": 350 225 + } 226 + } 227 + } 228 + ``` 229 + 230 + ## Example: `--no-wait` (fire-and-forget) 231 + 232 + ```json 233 + { 234 + "ok": true, 235 + "command": "send", 236 + "schema_version": "prowl.cli.send.v1", 237 + "data": { 238 + "target": { 239 + "worktree": { 240 + "id": "Prowl:/Users/onevcat/Projects/Prowl", 241 + "name": "Prowl", 242 + "path": "/Users/onevcat/Projects/Prowl", 243 + "root_path": "/Users/onevcat/Projects/Prowl", 244 + "kind": "git" 245 + }, 246 + "tab": { 247 + "id": "2FC00CF0-3974-4E1B-BEF8-7A08A8E3B7C0", 248 + "title": "Prowl 1", 249 + "selected": true 250 + }, 251 + "pane": { 252 + "id": "6E1A2A10-D99F-4E3F-920C-D93AA3C05764", 253 + "title": "zsh", 254 + "cwd": "/Users/onevcat/Projects/Prowl", 255 + "focused": true 256 + } 257 + }, 258 + "input": { 259 + "source": "argv", 260 + "characters": 5, 261 + "bytes": 5, 262 + "trailing_enter_sent": true 263 + }, 264 + "created_tab": false, 265 + "wait": null 198 266 } 199 267 } 200 268 ```