(self, args: str, context: CommandContext)
| 221 | """Copy the latest assistant response (or a code block) to the clipboard.""" |
| 222 | |
| 223 | async def run(self, args: str, context: CommandContext) -> InteractiveOutcome: |
| 224 | messages = getattr(context.conversation, "messages", None) or [] |
| 225 | texts = collect_recent_assistant_texts(messages) |
| 226 | if not texts: |
| 227 | return InteractiveOutcome(message="No assistant message to copy", display="user") |
| 228 | |
| 229 | # /copy N reaches back N-1 messages (TS copy.tsx:341-355). |
| 230 | age = 0 |
| 231 | arg = (args or "").strip() |
| 232 | if arg: |
| 233 | # int(arg) mirrors TS Number()+isInteger: accepts "+2"/"02", rejects |
| 234 | # floats and non-numerics. |
| 235 | try: |
| 236 | n = int(arg) |
| 237 | is_int = True |
| 238 | except ValueError: |
| 239 | n, is_int = 0, False |
| 240 | if not is_int or n < 1: |
| 241 | return InteractiveOutcome( |
| 242 | message=( |
| 243 | "Usage: /copy [N] where N is 1 (latest), 2, 3, … " |
| 244 | f"Got: {arg}" |
| 245 | ), |
| 246 | display="user", |
| 247 | ) |
| 248 | if n > len(texts): |
| 249 | noun = "message" if len(texts) == 1 else "messages" |
| 250 | return InteractiveOutcome( |
| 251 | message=f"Only {len(texts)} assistant {noun} available to copy", |
| 252 | display="user", |
| 253 | ) |
| 254 | age = n - 1 |
| 255 | |
| 256 | text = texts[age] |
| 257 | code_blocks = _extract_code_blocks(text) |
| 258 | |
| 259 | if not code_blocks or _copy_full_response_enabled(): |
| 260 | return InteractiveOutcome( |
| 261 | message=_copy_or_write(text, RESPONSE_FILENAME), display="user" |
| 262 | ) |
| 263 | |
| 264 | return await self._pick(context, text, code_blocks) |
| 265 | |
| 266 | async def _pick( |
| 267 | self, context: CommandContext, full_text: str, code_blocks: list[CodeBlock] |
no test coverage detected