mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-28 03:00:29 -04:00
feat(mothership): append
This commit is contained in:
@@ -75,6 +75,16 @@ vi.mock('@/lib/uploads/utils/file-utils', () => ({
|
||||
|
||||
vi.mock('@/lib/uploads/setup.server', () => ({}))
|
||||
|
||||
vi.mock('@/lib/execution/doc-vm', () => ({
|
||||
generatePdfFromCode: vi.fn().mockResolvedValue(Buffer.from('%PDF-compiled')),
|
||||
generateDocxFromCode: vi.fn().mockResolvedValue(Buffer.from('PK\x03\x04compiled')),
|
||||
generatePptxFromCode: vi.fn().mockResolvedValue(Buffer.from('PK\x03\x04compiled')),
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/uploads/contexts/workspace/workspace-file-manager', () => ({
|
||||
parseWorkspaceFileKey: vi.fn().mockReturnValue(undefined),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/api/files/utils', () => ({
|
||||
FileNotFoundError,
|
||||
createFileResponse: mockCreateFileResponse,
|
||||
|
||||
@@ -301,6 +301,85 @@ export const workspaceFileServerTool: BaseServerTool<WorkspaceFileArgs, Workspac
|
||||
}
|
||||
}
|
||||
|
||||
case 'append': {
|
||||
const fileId = (args as Record<string, unknown>).fileId as string | undefined
|
||||
const content = (args as Record<string, unknown>).content as string | undefined
|
||||
|
||||
if (!fileId) {
|
||||
return { success: false, message: 'fileId is required for append operation' }
|
||||
}
|
||||
if (!content) {
|
||||
return { success: false, message: 'content is required for append operation' }
|
||||
}
|
||||
|
||||
const fileRecord = await getWorkspaceFile(workspaceId, fileId)
|
||||
if (!fileRecord) {
|
||||
return { success: false, message: `File with ID "${fileId}" not found` }
|
||||
}
|
||||
|
||||
const currentBuffer = await downloadWsFile(fileRecord)
|
||||
const combined = `${currentBuffer.toString('utf-8')}\n${content}`
|
||||
|
||||
const appendLowerName = fileRecord.name?.toLowerCase() ?? ''
|
||||
const isPptxAppend = appendLowerName.endsWith('.pptx')
|
||||
const isDocxAppend = appendLowerName.endsWith('.docx')
|
||||
const isPdfAppend = appendLowerName.endsWith('.pdf')
|
||||
const isDocAppend = isPptxAppend || isDocxAppend || isPdfAppend
|
||||
|
||||
if (isDocAppend) {
|
||||
const formatName = isPptxAppend ? 'PPTX' : isDocxAppend ? 'DOCX' : 'PDF'
|
||||
const generator = isPptxAppend
|
||||
? generatePptxFromCode
|
||||
: isDocxAppend
|
||||
? generateDocxFromCode
|
||||
: generatePdfFromCode
|
||||
try {
|
||||
await generator(combined, workspaceId)
|
||||
} catch (err) {
|
||||
const msg = err instanceof Error ? err.message : String(err)
|
||||
return {
|
||||
success: false,
|
||||
message: `Appended ${formatName} code failed to compile: ${msg}. Fix the content and retry.`,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const appendSourceMime = isPptxAppend
|
||||
? PPTX_SOURCE_MIME
|
||||
: isDocxAppend
|
||||
? DOCX_SOURCE_MIME
|
||||
: isPdfAppend
|
||||
? PDF_SOURCE_MIME
|
||||
: undefined
|
||||
const appendBuffer = Buffer.from(combined, 'utf-8')
|
||||
assertServerToolNotAborted(context)
|
||||
await updateWorkspaceFileContent(
|
||||
workspaceId,
|
||||
fileId,
|
||||
context.userId,
|
||||
appendBuffer,
|
||||
appendSourceMime
|
||||
)
|
||||
|
||||
logger.info('Workspace file appended via copilot', {
|
||||
fileId,
|
||||
name: fileRecord.name,
|
||||
appendedSize: content.length,
|
||||
totalSize: appendBuffer.length,
|
||||
userId: context.userId,
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: `Content appended to "${fileRecord.name}" (${content.length} bytes added, ${appendBuffer.length} bytes total)`,
|
||||
data: {
|
||||
id: fileId,
|
||||
name: fileRecord.name,
|
||||
size: appendBuffer.length,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
case 'patch': {
|
||||
const fileId = (args as Record<string, unknown>).fileId as string | undefined
|
||||
const edits = (args as Record<string, unknown>).edits as
|
||||
|
||||
@@ -176,7 +176,7 @@ export type UserTableResult = z.infer<typeof UserTableResultSchema>
|
||||
|
||||
// workspace_file - shared schema used by server tool and Go catalog
|
||||
export const WorkspaceFileArgsSchema = z.object({
|
||||
operation: z.enum(['write', 'update', 'delete', 'rename', 'patch']),
|
||||
operation: z.enum(['write', 'update', 'append', 'delete', 'rename', 'patch']),
|
||||
args: z
|
||||
.object({
|
||||
fileId: z.string().optional(),
|
||||
|
||||
Reference in New Issue
Block a user