Commit 60a7381
committed
fix(tools): Isolate paste_text tmux buffer and tighten temp-file lifecycle
why: paste_text had three related state-management issues on the same
function:
1. Buffer clobber/leak. load-buffer with no -b wrote into tmux's
default unnamed buffer. In any interactive session this overwrote
whatever the operator had yanked. And if pane.cmd("paste-buffer",
"-d", ...) failed for any reason (pane dead, server error), the -d
never ran and the buffer leaked on the tmux server.
2. Temp-file disk leak on write failure. The with-block bound
tmppath = f.name *after* f.write(text). If f.write raised (OSError
disk full / quota), tmppath was never assigned, the subsequent
try/finally block was never reached, and the temp file created by
NamedTemporaryFile(delete=False) stayed on disk.
3. Silent stderr on subprocess failure. subprocess.run(..., check=True,
capture_output=True) raised CalledProcessError with tmux's stderr
attached, but the message agents saw was just "non-zero exit status
1" — no tmux diagnostic.
what:
- Generate a unique named buffer per call (mcp_paste_<uuid4 hex>) and
load into that. paste-buffer uses -b NAME -d so the delete only
affects the named buffer, leaving the user's unnamed buffer intact.
- Bind tmppath = f.name BEFORE f.write so cleanup always has a path.
- Use pathlib.Path(...).unlink(missing_ok=True) in finally.
- Wrap delete-buffer in contextlib.suppress(Exception) as a defensive
best-effort cleanup if paste-buffer raised before -d ran.
- Catch CalledProcessError on load-buffer and surface tmux's stderr
as a ToolError for actionable agent diagnostics.
- Add imports: contextlib (stdlib, module top), uuid (stdlib, module
top), namespace style per AGENTS.md §Imports.
- Add test_paste_text_does_not_clobber_unnamed_buffer: pre-populates
the unnamed buffer with a sentinel, calls paste_text, then asserts
the unnamed buffer still contains the sentinel AND no mcp_paste_*
named buffer leaks remain on the server.1 parent 3e96084 commit 60a7381
2 files changed
Lines changed: 67 additions & 13 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
| 10 | + | |
9 | 11 | | |
10 | 12 | | |
11 | 13 | | |
| |||
1172 | 1174 | | |
1173 | 1175 | | |
1174 | 1176 | | |
| 1177 | + | |
| 1178 | + | |
1175 | 1179 | | |
1176 | 1180 | | |
1177 | 1181 | | |
| |||
1181 | 1185 | | |
1182 | 1186 | | |
1183 | 1187 | | |
1184 | | - | |
1185 | | - | |
1186 | | - | |
1187 | | - | |
1188 | | - | |
1189 | | - | |
| 1188 | + | |
| 1189 | + | |
| 1190 | + | |
| 1191 | + | |
| 1192 | + | |
1190 | 1193 | | |
1191 | | - | |
| 1194 | + | |
| 1195 | + | |
| 1196 | + | |
| 1197 | + | |
| 1198 | + | |
| 1199 | + | |
| 1200 | + | |
1192 | 1201 | | |
1193 | 1202 | | |
1194 | 1203 | | |
1195 | 1204 | | |
1196 | 1205 | | |
1197 | 1206 | | |
1198 | | - | |
1199 | | - | |
1200 | | - | |
1201 | | - | |
1202 | | - | |
| 1207 | + | |
| 1208 | + | |
| 1209 | + | |
| 1210 | + | |
| 1211 | + | |
| 1212 | + | |
| 1213 | + | |
| 1214 | + | |
| 1215 | + | |
| 1216 | + | |
| 1217 | + | |
| 1218 | + | |
1203 | 1219 | | |
1204 | 1220 | | |
1205 | 1221 | | |
1206 | 1222 | | |
1207 | 1223 | | |
1208 | | - | |
| 1224 | + | |
| 1225 | + | |
| 1226 | + | |
| 1227 | + | |
| 1228 | + | |
| 1229 | + | |
| 1230 | + | |
1209 | 1231 | | |
1210 | 1232 | | |
1211 | 1233 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
912 | 912 | | |
913 | 913 | | |
914 | 914 | | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
0 commit comments