@@ -250,18 +250,32 @@ export function inferContextFromKey(key: string): StorageContext {
250250 }
251251
252252 // Workspace files: UUID-like ID followed by timestamp pattern
253- // Pattern: {uuid}/{timestamp}-{random}-{filename}
253+ // Pattern: {uuid}/{timestamp}-{random}-{filename} (cloud storage)
254254 if ( key . match ( / ^ [ a - f 0 - 9 - ] { 36 } \/ \d + - [ a - z 0 - 9 ] + - / ) ) {
255255 return 'workspace'
256256 }
257257
258+ // Local workspace files: UUID segments separated by underscore, then timestamp pattern
259+ // Pattern: {uuid}-{uuid}_{timestamp}-{random}-{filename} (local storage format)
260+ // This handles workspace files stored locally without cloud storage
261+ if ( key . match ( / ^ [ a - f 0 - 9 - ] { 36 } - [ a - f 0 - 9 - ] { 36 } _ \d + - [ a - z 0 - 9 ] + - / ) ) {
262+ return 'workspace'
263+ }
264+
258265 // Local execution files: UUID segments separated by underscores/hyphens
259266 // Pattern: {uuid}-{uuid}_{uuid}_{uuid}_{filename} (local storage format)
260267 // This handles execution files stored locally without cloud storage
261268 if ( key . match ( / ^ [ a - f 0 - 9 - ] { 36 } - [ a - f 0 - 9 - ] { 36 } _ [ a - f 0 - 9 - ] { 36 } _ [ a - f 0 - 9 - ] { 36 } _ / ) ) {
262269 return 'execution'
263270 }
264271
272+ // Profile pictures: UUID followed directly by filename
273+ // Pattern: {uuid}-{filename} (local storage format)
274+ // This handles profile pictures stored locally
275+ if ( key . match ( / ^ [ a - f 0 - 9 - ] { 36 } - [ ^ / ] + \. ( j p g | j p e g | p n g | g i f | w e b p | s v g ) $ / i) ) {
276+ return 'profile-pictures'
277+ }
278+
265279 // Copilot/General files: timestamp-random-filename (no path segments)
266280 // Pattern: {timestamp}-{random}-{filename}
267281 // NOTE: This is ambiguous - prefer explicit context parameter
@@ -326,7 +340,6 @@ export function processSingleFileToUserFile(
326340 requestId : string ,
327341 logger : Logger
328342) : InternalFileMetadata {
329- // If it already has all required fields, return as-is
330343 if ( file . id && file . key && file . uploadedAt && ( file as any ) . context ) {
331344 return file as unknown as InternalFileMetadata
332345 }
@@ -338,7 +351,6 @@ export function processSingleFileToUserFile(
338351 throw new Error ( `File has no storage key: ${ file . name || 'unknown' } ` )
339352 }
340353
341- // Determine context from key or file properties
342354 const context = ( file as any ) . context || inferContextFromKey ( storageKey )
343355
344356 const internalMetadata : InternalFileMetadata = {
@@ -403,16 +415,10 @@ export function processFilesToUserFiles(
403415export function sanitizeFilenameForMetadata ( filename : string ) : string {
404416 return (
405417 filename
406- // Remove non-ASCII characters (keep only printable ASCII 0x20-0x7E)
407418 . replace ( / [ ^ \x20 - \x7E ] / g, '' )
408- // Remove characters that are problematic in HTTP headers
409419 . replace ( / [ " \\ ] / g, '' )
410- // Replace multiple spaces with single space
411420 . replace ( / \s + / g, ' ' )
412- // Trim whitespace
413- . trim ( ) ||
414- // Provide fallback if completely sanitized
415- 'file'
421+ . trim ( ) || 'file'
416422 )
417423}
418424
0 commit comments