| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent fb04f19 commit e750db0
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -14,6 +14,12 @@ | |||
| 14 | 14 | class Commands: | |
| 15 | 15 | scraper = None | |
| 16 | 16 | ||
| 17 | + # Queue commands need the FULL text after the command name (including the | ||
| 18 | + # trailing space) passed as completion args, so nested slash-command | ||
| 19 | + # completion (e.g. "/queue /add <tab>") can see the inner command and its | ||
| 20 | + # arguments (plan 9.13). Both completers (io.py, tui/app.py) consult this. | ||
| 21 | + FULL_ARGS_COMPLETION_COMMANDS = ("/queue", "/insert-queue") | ||
| 22 | + | ||
| 17 | 23 | def _get_coder(self): | |
| 18 | 24 | """Return coder via weak reference, or None if collected.""" | |
| 19 | 25 | if self._coder_ref is not None: | |
@@ -90,7 +96,7 @@ def __init__( | |||
| 90 | 96 | self.last_command_show_notification = True | |
| 91 | 97 | ||
| 92 | 98 | # Commands that should NOT trigger auto-processing of the queue | |
| 93 | - self._MANAGEMENT_COMMANDS = {"queue", "list-queue", "remove-queue"} | ||
| 99 | + self._MANAGEMENT_COMMANDS = {"queue", "list-queue", "remove-queue", "run-queue"} | ||
| 94 | 100 | ||
| 95 | 101 | def _load_custom_commands(self, custom_commands): | |
| 96 | 102 | """ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,10 +1,12 @@ | |||
| 1 | 1 | """Insert-queue command for CLI-33: inserts a prompt at a specific queue position.""" | |
| 2 | 2 | ||
| 3 | + import asyncio | ||
| 3 | 4 | from typing import List | |
| 4 | 5 | ||
| 5 | 6 | from cecli.commands.utils.base_command import BaseCommand | |
| 6 | 7 | from cecli.commands.utils.helpers import format_command_result | |
| 7 | 8 | from cecli.helpers import command_queue | |
| 9 | + from cecli.signals import SwitchCoderSignal | ||
| 8 | 10 | ||
| 9 | 11 | ||
| 10 | 12 | class InsertQueueCommand(BaseCommand): | |
@@ -60,6 +62,22 @@ async def execute(cls, io, coder, args, **kwargs): | |||
| 60 | 62 | try: | |
| 61 | 63 | item = command_queue.insert_prompt(coder, prompt_text, index) | |
| 62 | 64 | io.tool_output(f"Prompt inserted at position {index + 1} (id: {item['id']})") | |
| 65 | + | ||
| 66 | + # Idle-immediate: when no request is in flight there is nothing to | ||
| 67 | + # wait for, so drain the queue right away. When a request IS in | ||
| 68 | + # flight, the queue auto-drains when run_one() completes. | ||
| 69 | + target = command_queue.get_active_coder(coder) | ||
| 70 | + if command_queue.idle_drain_needed(target): | ||
| 71 | + try: | ||
| 72 | + await target.process_prompt_queue() | ||
| 73 | + except (KeyboardInterrupt, asyncio.CancelledError): | ||
| 74 | + # The interrupted item was re-queued; let the user know the queue paused. | ||
| 75 | + io.tool_output("Queue processing paused. Use /run-queue to resume.") | ||
| 76 | + except (SwitchCoderSignal, SystemExit): | ||
| 77 | + raise | ||
| 78 | + except Exception as e: | ||
| 79 | + return format_command_result(io, cls.NORM_NAME, "", error=str(e)) | ||
| 80 | + | ||
| 63 | 81 | return f"Successfully executed {cls.NORM_NAME}." | |
| 64 | 82 | except ValueError as e: | |
| 65 | 83 | return format_command_result(io, cls.NORM_NAME, "", error=str(e)) | |
@@ -68,8 +86,20 @@ async def execute(cls, io, coder, args, **kwargs): | |||
| 68 | 86 | ||
| 69 | 87 | @classmethod | |
| 70 | 88 | def get_completions(cls, io, coder, args) -> List[str]: | |
| 71 | - """Get completion options for insert-queue command.""" | ||
| 72 | - return [] | ||
| 89 | + """Get completion options for insert-queue command. | ||
| 90 | + | ||
| 91 | + Args are "<index> <prompt text>"; once the index token and a space | ||
| 92 | + are present, mirror the nested prompt's completions (e.g. a nested | ||
| 93 | + slash command delegates to the original command's completions). | ||
| 94 | + """ | ||
| 95 | + text = args or "" | ||
| 96 | + first_space = text.find(" ") | ||
| 97 | + if first_space == -1: | ||
| 98 | + # Still typing the index; suggest valid positions. | ||
| 99 | + if not coder.commands: | ||
| 100 | + return [] | ||
| 101 | + return [str(i) for i in range(1, command_queue.get_queue_length(coder) + 2)] | ||
| 102 | + return command_queue.nested_command_completions(coder, text[first_space + 1 :]) | ||
| 73 | 103 | ||
| 74 | 104 | @classmethod | |
| 75 | 105 | def get_help(cls) -> str: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,9 +2,12 @@ | |||
| 2 | 2 | ||
| 3 | 3 | from typing import List | |
| 4 | 4 | ||
| 5 | + import asyncio | ||
| 6 | + | ||
| 5 | 7 | from cecli.commands.utils.base_command import BaseCommand | |
| 6 | 8 | from cecli.commands.utils.helpers import format_command_result | |
| 7 | 9 | from cecli.helpers import command_queue | |
| 10 | + from cecli.signals import SwitchCoderSignal | ||
| 8 | 11 | ||
| 9 | 12 | ||
| 10 | 13 | class QueueCommand(BaseCommand): | |
@@ -59,6 +62,22 @@ async def execute(cls, io, coder, args, **kwargs): | |||
| 59 | 62 | item = command_queue.enqueue_prompt(coder, prompt_text) | |
| 60 | 63 | position = command_queue.get_queue_length(coder) | |
| 61 | 64 | io.tool_output(f"Prompt queued at position {position} (id: {item['id']})") | |
| 65 | + | ||
| 66 | + # Idle-immediate: when no request is in flight there is nothing to | ||
| 67 | + # wait for, so drain the queue right away. When a request IS in | ||
| 68 | + # flight, the queue auto-drains when run_one() completes. | ||
| 69 | + target = command_queue.get_active_coder(coder) | ||
| 70 | + if command_queue.idle_drain_needed(target): | ||
| 71 | + try: | ||
| 72 | + await target.process_prompt_queue() | ||
| 73 | + except (KeyboardInterrupt, asyncio.CancelledError): | ||
| 74 | + # The interrupted item was re-queued; let the user know the queue paused. | ||
| 75 | + io.tool_output("Queue processing paused. Use /run-queue to resume.") | ||
| 76 | + except (SwitchCoderSignal, SystemExit): | ||
| 77 | + raise | ||
| 78 | + except Exception as e: | ||
| 79 | + return format_command_result(io, cls.NORM_NAME, "", error=str(e)) | ||
| 80 | + | ||
| 62 | 81 | return f"Successfully executed {cls.NORM_NAME}." | |
| 63 | 82 | except ValueError as e: | |
| 64 | 83 | return format_command_result(io, cls.NORM_NAME, "", error=str(e)) | |
@@ -67,8 +86,12 @@ async def execute(cls, io, coder, args, **kwargs): | |||
| 67 | 86 | ||
| 68 | 87 | @classmethod | |
| 69 | 88 | def get_completions(cls, io, coder, args) -> List[str]: | |
| 70 | - """Get completion options for queue command.""" | ||
| 71 | - return [] | ||
| 89 | + """Get completion options for queue command. | ||
| 90 | + | ||
| 91 | + When the queued prompt starts with a slash command, mirror the | ||
| 92 | + original command's completions (e.g. /queue /add <tab> offers files). | ||
| 93 | + """ | ||
| 94 | + return command_queue.nested_command_completions(coder, args) | ||
| 72 | 95 | ||
| 73 | 96 | @classmethod | |
| 74 | 97 | def get_help(cls) -> str: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -265,7 +265,20 @@ def get_command_completions(self, document, complete_event, text, words): | |||
| 265 | 265 | yield from raw_completer(document, complete_event) | |
| 266 | 266 | return | |
| 267 | 267 | ||
| 268 | - candidates = self.commands.get_completions(cmd, partial) | ||
| 268 | + # Nested-host commands (/queue, /insert-queue) need the FULL text after | ||
| 269 | + # the command name (trailing space preserved) so inner slash-command | ||
| 270 | + # argument completion works (e.g. "/queue /add <tab>") - plan 9.13. | ||
| 271 | + if cmd in self.commands.FULL_ARGS_COMPLETION_COMMANDS: | ||
| 272 | + nested_text = text[len(words[0]) :].lstrip() | ||
| 273 | + candidates = self.commands.get_completions(cmd, nested_text) | ||
| 274 | + # The substring filter and start_position below operate on the last | ||
| 275 | + # word; an empty/trailing-space nested text means "no partial yet". | ||
| 276 | + if not nested_text or nested_text[-1].isspace(): | ||
| 277 | + partial = "" | ||
| 278 | + else: | ||
| 279 | + partial = nested_text.split()[-1].lower() | ||
| 280 | + else: | ||
| 281 | + candidates = self.commands.get_completions(cmd, partial) | ||
| 269 | 282 | ||
| 270 | 283 | if candidates is None: | |
| 271 | 284 | return | |
| Back | FazBrowse Home | New Git URL |
0 commit comments