@@ -408,21 +408,18 @@ export async function registerUploadedWorkspaceFile(params: {
408408}
409409
410410/**
411- * Inserts ` (n)` before the last extension, mirroring `withCopySuffix` but starting at n=1
412- * for the second occurrence (so `image.png`, `image (2).png`, `image (3).png` ).
413- * Extensionless names get `name (n)`; dotfiles like `.env` are treated as extensionless .
411+ * Like `withCopySuffix` but with `n=1` meaning "no suffix" — used by retry loops where
412+ * the first attempt should try the original name ( `image.png`, `image (2).png`, ... ).
413+ * Exported for tests .
414414 */
415415export function suffixedName ( name : string , n : number ) : string {
416- if ( n <= 1 ) return name
417- const dot = name . lastIndexOf ( '.' )
418- if ( dot <= 0 || dot === name . length - 1 ) return `${ name } (${ n } )`
419- return `${ name . slice ( 0 , dot ) } (${ n } )${ name . slice ( dot ) } `
416+ return n <= 1 ? name : withCopySuffix ( name , n )
420417}
421418
422419const MAX_CHAT_DISPLAY_NAME_RETRIES = 1000
423420
424421/** Postgres constraint name for the partial unique index on `(chat_id, display_name)`. */
425- const CHAT_DISPLAY_NAME_INDEX = 'workspace_files_chat_display_name_unique'
422+ export const CHAT_DISPLAY_NAME_INDEX = 'workspace_files_chat_display_name_unique'
426423
427424/**
428425 * Track a file that was already uploaded to workspace S3 as a chat-scoped upload.
@@ -485,13 +482,8 @@ export async function trackChatUpload(
485482 )
486483 return { displayName : candidate }
487484 } catch ( error ) {
488- /**
489- * Only retry on a collision against the chat displayName index. Any other 23505
490- * (the active-key index from a concurrent insert with the same s3Key, or a
491- * primary-key collision) means a different invariant is contested — bumping the
492- * suffix would silently rename whichever row eventually owns the s3Key, including
493- * a row another caller has already returned to its client.
494- */
485+ // Other 23505s (e.g. active-key collision from a racing same-s3Key insert) signal
486+ // a different invariant — retrying would silently rename a row another caller owns.
495487 if (
496488 getPostgresErrorCode ( error ) === '23505' &&
497489 getPostgresConstraintName ( error ) === CHAT_DISPLAY_NAME_INDEX
0 commit comments