Skip to content

Commit 4a62f83

Browse files
fix(message): resolve file paths to absolute when serializing (#898)
* fix(message): resolve file paths to absolute when serializing Files attached to messages (e.g., images for vision) are now resolved to absolute paths when the message is serialized via to_dict(). This prevents FileNotFoundError crashes when the working directory changes after attaching files to a message. Fixes #262 * style: fix import order in test_message.py
1 parent 2718cb3 commit 4a62f83

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

gptme/message.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ def to_dict(self, keys=None) -> dict:
8585
"timestamp": self.timestamp.isoformat(),
8686
}
8787
if self.files:
88-
d["files"] = [str(f) for f in self.files]
88+
# Resolve to absolute paths to prevent issues when working directory changes
89+
d["files"] = [str(f.resolve()) for f in self.files]
8990
if self.pinned:
9091
d["pinned"] = True
9192
if self.hide:

tests/test_message.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,50 @@ def test_format_msgs_preserves_codeblocks():
106106
outputs = format_msgs([msg], highlight=True)
107107
assert len(outputs) == 1
108108
# Code blocks should still work with syntax highlighting
109+
110+
111+
def test_message_files_resolve_to_absolute(tmp_path, monkeypatch):
112+
"""Test that file paths are resolved to absolute paths when serializing.
113+
114+
This prevents issues when the working directory changes after attaching
115+
files to a message. See issue #262.
116+
"""
117+
import os
118+
from pathlib import Path
119+
120+
from gptme.message import Message
121+
122+
# Create a test file in tmp_path
123+
test_file = tmp_path / "test_image.png"
124+
test_file.write_bytes(b"fake image data")
125+
126+
# Change to tmp_path and create a message with a relative path
127+
original_cwd = os.getcwd()
128+
try:
129+
monkeypatch.chdir(tmp_path)
130+
msg = Message("user", "Check this image", files=[Path("test_image.png")])
131+
132+
# Serialize the message
133+
d = msg.to_dict()
134+
135+
# The file path should be absolute in the serialized dict
136+
assert d["files"][0] == str(test_file.resolve())
137+
assert Path(d["files"][0]).is_absolute()
138+
139+
# Change to a different directory
140+
other_dir = tmp_path / "other"
141+
other_dir.mkdir()
142+
monkeypatch.chdir(other_dir)
143+
144+
# Deserialize and verify the path still works
145+
# (simulating what logmanager._gen_read_jsonl does)
146+
loaded_files = [Path(f) for f in d.get("files", [])]
147+
loaded_msg = Message(
148+
d["role"],
149+
d["content"],
150+
files=loaded_files,
151+
)
152+
assert len(loaded_msg.files) == 1
153+
assert loaded_msg.files[0].exists()
154+
finally:
155+
os.chdir(original_cwd)

0 commit comments

Comments
 (0)