Skip to content

Commit 031e12f

Browse files
author
Theodore Li
committed
--wip-- [skip ci]
1 parent fdb6039 commit 031e12f

File tree

4 files changed

+50
-87
lines changed

4 files changed

+50
-87
lines changed

apps/sim/app/api/tools/sim-file/manage/route.ts renamed to apps/sim/app/api/tools/file/manage/route.ts

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,11 @@ import {
88
updateWorkspaceFileContent,
99
uploadWorkspaceFile,
1010
} from '@/lib/uploads/contexts/workspace/workspace-file-manager'
11+
import { getFileExtension, getMimeTypeFromExtension } from '@/lib/uploads/utils/file-utils'
1112

1213
export const dynamic = 'force-dynamic'
1314

14-
const logger = createLogger('SimFileManageAPI')
15-
16-
const EXT_TO_MIME: Record<string, string> = {
17-
'.txt': 'text/plain',
18-
'.md': 'text/markdown',
19-
'.html': 'text/html',
20-
'.json': 'application/json',
21-
'.csv': 'text/csv',
22-
'.xml': 'application/xml',
23-
'.yaml': 'application/x-yaml',
24-
'.yml': 'application/x-yaml',
25-
}
26-
27-
function inferContentType(fileName: string, explicitType?: string): string {
28-
if (explicitType) return explicitType
29-
const ext = fileName.slice(fileName.lastIndexOf('.')).toLowerCase()
30-
return EXT_TO_MIME[ext] || 'text/plain'
31-
}
15+
const logger = createLogger('FileManageAPI')
3216

3317
export async function POST(request: NextRequest) {
3418
const auth = await checkInternalAuth(request, { requireWorkflowId: false })
@@ -101,7 +85,7 @@ export async function POST(request: NextRequest) {
10185
})
10286
}
10387

104-
const mimeType = inferContentType(fileName, contentType)
88+
const mimeType = contentType || getMimeTypeFromExtension(getFileExtension(fileName))
10589
const fileBuffer = Buffer.from(content ?? '', 'utf-8')
10690
const result = await uploadWorkspaceFile(
10791
workspaceId,
@@ -144,7 +128,7 @@ export async function POST(request: NextRequest) {
144128
const fileBuffer = Buffer.from(finalContent, 'utf-8')
145129
await updateWorkspaceFileContent(workspaceId, fileId, userId, fileBuffer)
146130

147-
logger.info('Sim file written', {
131+
logger.info('File written', {
148132
fileId,
149133
name: fileRecord.name,
150134
size: fileBuffer.length,
@@ -174,7 +158,7 @@ export async function POST(request: NextRequest) {
174158
}
175159
} catch (error) {
176160
const message = error instanceof Error ? error.message : 'Unknown error'
177-
logger.error('Sim file operation failed', { operation, error: message })
161+
logger.error('File operation failed', { operation, error: message })
178162
return NextResponse.json({ success: false, error: message }, { status: 500 })
179163
}
180164
}

apps/sim/lib/copilot/tools/server/files/workspace-file.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,10 @@ import {
88
updateWorkspaceFileContent,
99
uploadWorkspaceFile,
1010
} from '@/lib/uploads/contexts/workspace/workspace-file-manager'
11+
import { getFileExtension, getMimeTypeFromExtension } from '@/lib/uploads/utils/file-utils'
1112

1213
const logger = createLogger('WorkspaceFileServerTool')
1314

14-
const EXT_TO_MIME: Record<string, string> = {
15-
'.txt': 'text/plain',
16-
'.md': 'text/markdown',
17-
'.html': 'text/html',
18-
'.json': 'application/json',
19-
'.csv': 'text/csv',
20-
}
21-
22-
function inferContentType(fileName: string, explicitType?: string): string {
23-
if (explicitType) return explicitType
24-
const ext = fileName.slice(fileName.lastIndexOf('.')).toLowerCase()
25-
return EXT_TO_MIME[ext] || 'text/plain'
26-
}
27-
2815
export const workspaceFileServerTool: BaseServerTool<WorkspaceFileArgs, WorkspaceFileResult> = {
2916
name: 'workspace_file',
3017
async execute(
@@ -58,7 +45,7 @@ export const workspaceFileServerTool: BaseServerTool<WorkspaceFileArgs, Workspac
5845
return { success: false, message: 'content is required for write operation' }
5946
}
6047

61-
const contentType = inferContentType(fileName, explicitType)
48+
const contentType = explicitType || getMimeTypeFromExtension(getFileExtension(fileName))
6249
const fileBuffer = Buffer.from(content, 'utf-8')
6350
const result = await uploadWorkspaceFile(
6451
workspaceId,

apps/sim/lib/uploads/contexts/workspace/workspace-file-manager.ts

Lines changed: 42 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -251,76 +251,68 @@ export async function trackChatUpload(
251251
}
252252

253253
/**
254-
* Check if a file with the same name already exists in workspace
254+
* Check if a file with the same name already exists in workspace.
255+
* Throws on DB errors so callers can distinguish "not found" from "lookup failed."
255256
*/
256257
export async function fileExistsInWorkspace(
257258
workspaceId: string,
258259
fileName: string
259260
): Promise<boolean> {
260-
try {
261-
const existing = await db
262-
.select()
263-
.from(workspaceFiles)
264-
.where(
265-
and(
266-
eq(workspaceFiles.workspaceId, workspaceId),
267-
eq(workspaceFiles.originalName, fileName),
268-
eq(workspaceFiles.context, 'workspace'),
269-
isNull(workspaceFiles.deletedAt)
270-
)
261+
const existing = await db
262+
.select()
263+
.from(workspaceFiles)
264+
.where(
265+
and(
266+
eq(workspaceFiles.workspaceId, workspaceId),
267+
eq(workspaceFiles.originalName, fileName),
268+
eq(workspaceFiles.context, 'workspace'),
269+
isNull(workspaceFiles.deletedAt)
271270
)
272-
.limit(1)
271+
)
272+
.limit(1)
273273

274-
return existing.length > 0
275-
} catch (error) {
276-
logger.error(`Failed to check file existence for ${fileName}:`, error)
277-
return false
278-
}
274+
return existing.length > 0
279275
}
280276

281277
/**
282278
* Look up a single active workspace file by its original name.
283-
* Returns the record if found, or null otherwise.
279+
* Returns the record if found, or null if no matching file exists.
280+
* Throws on DB errors so callers can distinguish "not found" from "lookup failed."
284281
*/
285282
export async function getWorkspaceFileByName(
286283
workspaceId: string,
287284
fileName: string
288285
): Promise<WorkspaceFileRecord | null> {
289-
try {
290-
const files = await db
291-
.select()
292-
.from(workspaceFiles)
293-
.where(
294-
and(
295-
eq(workspaceFiles.workspaceId, workspaceId),
296-
eq(workspaceFiles.originalName, fileName),
297-
eq(workspaceFiles.context, 'workspace'),
298-
isNull(workspaceFiles.deletedAt)
299-
)
286+
const files = await db
287+
.select()
288+
.from(workspaceFiles)
289+
.where(
290+
and(
291+
eq(workspaceFiles.workspaceId, workspaceId),
292+
eq(workspaceFiles.originalName, fileName),
293+
eq(workspaceFiles.context, 'workspace'),
294+
isNull(workspaceFiles.deletedAt)
300295
)
301-
.limit(1)
296+
)
297+
.limit(1)
302298

303-
if (files.length === 0) return null
299+
if (files.length === 0) return null
304300

305-
const { getServePathPrefix } = await import('@/lib/uploads')
306-
const pathPrefix = getServePathPrefix()
301+
const { getServePathPrefix } = await import('@/lib/uploads')
302+
const pathPrefix = getServePathPrefix()
307303

308-
const file = files[0]
309-
return {
310-
id: file.id,
311-
workspaceId: file.workspaceId || workspaceId,
312-
name: file.originalName,
313-
key: file.key,
314-
path: `${pathPrefix}${encodeURIComponent(file.key)}?context=workspace`,
315-
size: file.size,
316-
type: file.contentType,
317-
uploadedBy: file.userId,
318-
deletedAt: file.deletedAt,
319-
uploadedAt: file.uploadedAt,
320-
}
321-
} catch (error) {
322-
logger.error(`Failed to get workspace file by name "${fileName}":`, error)
323-
return null
304+
const file = files[0]
305+
return {
306+
id: file.id,
307+
workspaceId: file.workspaceId || workspaceId,
308+
name: file.originalName,
309+
key: file.key,
310+
path: `${pathPrefix}${encodeURIComponent(file.key)}?context=workspace`,
311+
size: file.size,
312+
type: file.contentType,
313+
uploadedBy: file.userId,
314+
deletedAt: file.deletedAt,
315+
uploadedAt: file.uploadedAt,
324316
}
325317
}
326318

apps/sim/tools/file/write.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export const fileWriteTool: ToolConfig<FileWriteParams, ToolResponse> = {
5454
},
5555

5656
request: {
57-
url: '/api/tools/sim-file/manage',
57+
url: '/api/tools/file/manage',
5858
method: 'POST',
5959
headers: () => ({ 'Content-Type': 'application/json' }),
6060
body: (params) => ({

0 commit comments

Comments
 (0)