Skip to content

Commit 43b2510

Browse files
authored
fix: issue 34, missing files (#38)
* fix: issue 34, missing files * chore: lint fix
1 parent 604c91d commit 43b2510

4 files changed

Lines changed: 401 additions & 5 deletions

File tree

src/api/files.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,36 @@ async def upload_file(
9999

100100
uploaded_files = []
101101

102-
# Create an actual session in Redis for this upload
103-
session_metadata = {}
102+
# Resolve or create session for this upload.
103+
# When entity_id is provided, reuse the existing session for that
104+
# entity so that multiple file uploads land in the same session
105+
# (fixes issue #34 where separate uploads created isolated sessions).
106+
session_id = None
104107
if entity_id:
105-
session_metadata["entity_id"] = entity_id
108+
try:
109+
existing = await session_service.list_sessions_by_entity(entity_id, limit=1)
110+
if existing:
111+
candidate = existing[0]
112+
if getattr(candidate.status, "value", str(candidate.status)) == "active":
113+
session_id = candidate.session_id
114+
logger.info(
115+
"Reusing existing session for entity",
116+
session_id=session_id,
117+
entity_id=entity_id,
118+
)
119+
except Exception as e:
120+
logger.warning(
121+
"Failed to look up session by entity_id",
122+
entity_id=entity_id,
123+
error=str(e),
124+
)
106125

107-
session = await session_service.create_session(SessionCreate(metadata=session_metadata))
108-
session_id = session.session_id
126+
if not session_id:
127+
session_metadata = {}
128+
if entity_id:
129+
session_metadata["entity_id"] = entity_id
130+
session = await session_service.create_session(SessionCreate(metadata=session_metadata))
131+
session_id = session.session_id
109132

110133
for file in upload_files:
111134
# Read file content

src/services/interfaces.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ async def cleanup_session_files(self, session_id: str) -> int:
138138
"""Clean up all files for a session. Returns count of deleted files."""
139139
pass
140140

141+
@abstractmethod
142+
async def store_uploaded_file(
143+
self, session_id: str, filename: str, content: bytes, content_type: str | None = None
144+
) -> str:
145+
"""Store an uploaded file directly. Returns file_id."""
146+
pass
147+
141148
@abstractmethod
142149
async def store_execution_output_file(self, session_id: str, filename: str, content: bytes) -> str:
143150
"""Store a file generated during execution. Returns file_id."""

src/services/orchestrator.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,32 @@ async def _mount_files(self, ctx: ExecutionContext) -> list[dict[str, Any]]:
348348
)
349349
mounted_ids.add(key)
350350

351+
# Consolidate cross-session files into the chosen session (issue #34).
352+
# When files are uploaded in separate sessions (e.g. entity_id=null),
353+
# copy them into the execution session so subsequent requests can find them.
354+
if ctx.session_id and file_ref.session_id != ctx.session_id:
355+
try:
356+
await self.file_service.store_uploaded_file(
357+
session_id=ctx.session_id,
358+
filename=file_info.filename,
359+
content=content,
360+
content_type=file_info.content_type,
361+
)
362+
logger.info(
363+
"Consolidated cross-session file",
364+
source_session=file_ref.session_id,
365+
target_session=ctx.session_id[:12],
366+
filename=file_info.filename,
367+
)
368+
except Exception as e:
369+
logger.warning(
370+
"Failed to consolidate cross-session file",
371+
source_session=file_ref.session_id,
372+
target_session=ctx.session_id[:12],
373+
filename=file_info.filename,
374+
error=str(e),
375+
)
376+
351377
logger.debug(
352378
"Mounted file for execution",
353379
session_id=file_ref.session_id,

0 commit comments

Comments
 (0)