Skip to content
314 changes: 309 additions & 5 deletions apps/sim/blocks/blocks/onedrive.ts

Large diffs are not rendered by default.

97 changes: 97 additions & 0 deletions apps/sim/tools/onedrive/copy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { createLogger } from '@sim/logger'
import type { OneDriveCopyResponse, OneDriveToolParams } from '@/tools/onedrive/types'
import type { ToolConfig } from '@/tools/types'

const logger = createLogger('OneDriveCopyTool')

/**
* Microsoft Graph processes driveItem copies asynchronously: a successful request returns
* `202 Accepted` with a `Location` header pointing to a monitor URL, not the copied item itself.
* See https://learn.microsoft.com/en-us/graph/api/driveitem-copy
*/
export const copyTool: ToolConfig<OneDriveToolParams, OneDriveCopyResponse> = {
id: 'onedrive_copy',
name: 'Copy OneDrive File',
description: 'Copy a file or folder to another location within OneDrive',
version: '1.0',

oauth: {
required: true,
provider: 'onedrive',
},

params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the OneDrive API',
},
fileId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the file or folder to copy',
},
destinationFolderId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the destination parent folder',
},
destinationFileName: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional new name for the copy (defaults to the original name)',
},
},

request: {
url: (params) =>
`https://graph.microsoft.com/v1.0/me/drive/items/${encodeURIComponent(params.fileId || '')}/copy`,
method: 'POST',
headers: (params) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
}),
body: (params) => ({
parentReference: { id: params.destinationFolderId },
...(params.destinationFileName && { name: params.destinationFileName }),
}),
},

transformResponse: async (response: Response, params?: OneDriveToolParams) => {
if (response.status !== 202) {
const data = await response.json().catch(() => ({}))
throw new Error(data.error?.message || 'Failed to start OneDrive copy')
}

const monitorUrl = response.headers.get('location') || undefined

logger.info('OneDrive copy accepted for async processing', {
fileId: params?.fileId,
monitorUrl,
})

return {
success: true,
output: {
sourceFileId: params?.fileId || '',
name: params?.destinationFileName,
monitorUrl,
},
}
},

outputs: {
success: { type: 'boolean', description: 'Whether the copy request was accepted' },
sourceFileId: { type: 'string', description: 'The ID of the file or folder that was copied' },
name: { type: 'string', description: 'The requested name for the copy, if provided' },
monitorUrl: {
type: 'string',
description:
'URL to poll for the status of the asynchronous copy operation (copy completes in the background)',
},
},
}
10 changes: 2 additions & 8 deletions apps/sim/tools/onedrive/create_folder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,19 @@ export const createFolderTool: ToolConfig<OneDriveToolParams, OneDriveUploadResp
visibility: 'user-or-llm',
description: 'Name of the folder to create (e.g., "My Documents", "Project Files")',
},
folderSelector: {
folderId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Parent folder ID to create the folder in (e.g., "01BYE5RZ6QN3ZWBTUFOFD3GSPGOHDJD36M")',
},
manualFolderId: {
type: 'string',
required: false,
visibility: 'hidden',
description: 'Manually entered parent folder ID (advanced mode)',
},
},

request: {
url: (params) => {
// Use specific parent folder URL if parentId is provided
const parentFolderId = params.manualFolderId || params.folderSelector
const parentFolderId = params.folderId?.trim()
if (parentFolderId) {
return `https://graph.microsoft.com/v1.0/me/drive/items/${encodeURIComponent(parentFolderId)}/children`
}
Expand Down
80 changes: 80 additions & 0 deletions apps/sim/tools/onedrive/create_share_link.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import type { OneDriveShareLinkResponse, OneDriveToolParams } from '@/tools/onedrive/types'
import type { ToolConfig } from '@/tools/types'

export const createShareLinkTool: ToolConfig<OneDriveToolParams, OneDriveShareLinkResponse> = {
id: 'onedrive_create_share_link',
name: 'Create OneDrive Sharing Link',
description: 'Create a view or edit sharing link for a OneDrive file or folder',
version: '1.0',

oauth: {
required: true,
provider: 'onedrive',
},

params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the OneDrive API',
},
fileId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the file or folder to share',
},
linkType: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Type of link to create: "view" (read-only), "edit" (read-write), or "embed"',
},
linkScope: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Who can use the link: "anonymous" (anyone), "organization" (tenant members), or "users" (specific people)',
},
},

request: {
url: (params) =>
`https://graph.microsoft.com/v1.0/me/drive/items/${encodeURIComponent(params.fileId || '')}/createLink`,
method: 'POST',
headers: (params) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
}),
body: (params) => ({
type: params.linkType || 'view',
...(params.linkScope && { scope: params.linkScope }),
}),
Comment thread
waleedlatif1 marked this conversation as resolved.
},

transformResponse: async (response: Response) => {
const data = await response.json()

return {
success: true,
output: {
link: {
type: data.link?.type,
scope: data.link?.scope,
webUrl: data.link?.webUrl,
webHtml: data.link?.webHtml,
},
},
}
},

outputs: {
success: { type: 'boolean', description: 'Whether the sharing link was created successfully' },
link: {
type: 'object',
description: 'The created sharing link, including its type, scope, and URL',
},
},
}
64 changes: 64 additions & 0 deletions apps/sim/tools/onedrive/get_drive_info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import type { OneDriveGetDriveInfoResponse, OneDriveToolParams } from '@/tools/onedrive/types'
import type { ToolConfig } from '@/tools/types'

export const getDriveInfoTool: ToolConfig<OneDriveToolParams, OneDriveGetDriveInfoResponse> = {
id: 'onedrive_get_drive_info',
name: 'Get OneDrive Info',
description: 'Get information about the OneDrive drive, including storage quota',
version: '1.0',

oauth: {
required: true,
provider: 'onedrive',
},

params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the OneDrive API',
},
},

request: {
url: () => 'https://graph.microsoft.com/v1.0/me/drive',
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.accessToken}`,
}),
},

transformResponse: async (response: Response) => {
const data = await response.json()

return {
success: true,
output: {
driveId: data.id,
driveType: data.driveType,
webUrl: data.webUrl,
owner: data.owner?.user?.displayName ?? null,
quota: {
total: data.quota?.total ?? 0,
used: data.quota?.used ?? 0,
remaining: data.quota?.remaining ?? 0,
deleted: data.quota?.deleted ?? 0,
state: data.quota?.state ?? 'normal',
},
},
}
},

outputs: {
success: { type: 'boolean', description: 'Whether the drive info was retrieved' },
driveId: { type: 'string', description: 'The ID of the drive' },
driveType: { type: 'string', description: 'The type of drive (e.g., "personal", "business")' },
webUrl: { type: 'string', description: 'URL to the drive in the browser' },
owner: { type: 'string', description: 'Display name of the drive owner', optional: true },
quota: {
type: 'object',
description: 'Storage quota information in bytes (total, used, remaining, deleted, state)',
},
},
}
84 changes: 84 additions & 0 deletions apps/sim/tools/onedrive/get_item.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import type {
MicrosoftGraphDriveItem,
OneDriveGetItemResponse,
OneDriveToolParams,
} from '@/tools/onedrive/types'
import type { ToolConfig } from '@/tools/types'

export const getItemTool: ToolConfig<OneDriveToolParams, OneDriveGetItemResponse> = {
id: 'onedrive_get_item',
name: 'Get OneDrive Item Metadata',
description: 'Get metadata for a specific OneDrive file or folder by ID, or the drive root',
version: '1.0',

oauth: {
required: true,
provider: 'onedrive',
},

params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the OneDrive API',
},
fileId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'The ID of the file or folder to retrieve (e.g., "01BYE5RZ6QN3ZWBTUFOFD3GSPGOHDJD36M"). Leave empty to get the drive root folder',
},
},

request: {
url: (params) => {
const fileId = params.fileId?.trim()
const baseUrl = fileId
? `https://graph.microsoft.com/v1.0/me/drive/items/${encodeURIComponent(fileId)}`
: 'https://graph.microsoft.com/v1.0/me/drive/root'

const url = new URL(baseUrl)
url.searchParams.append(
'$select',
'id,name,file,folder,webUrl,size,createdDateTime,lastModifiedDateTime,parentReference,@microsoft.graph.downloadUrl'
)
return url.toString()
},
method: 'GET',
headers: (params) => ({
Authorization: `Bearer ${params.accessToken}`,
}),
},

transformResponse: async (response: Response) => {
const data: MicrosoftGraphDriveItem = await response.json()

return {
success: true,
output: {
file: {
id: data.id,
name: data.name,
mimeType: data.file?.mimeType || (data.folder ? 'application/folder' : 'unknown'),
webViewLink: data.webUrl,
webContentLink: data['@microsoft.graph.downloadUrl'],
size: data.size?.toString() || '0',
createdTime: data.createdDateTime,
modifiedTime: data.lastModifiedDateTime,
parents: data.parentReference ? [data.parentReference.id] : [],
},
},
}
},

outputs: {
success: { type: 'boolean', description: 'Whether the item metadata was retrieved' },
file: {
type: 'object',
description:
'The file or folder metadata, including id, name, webViewLink, size, and timestamps',
},
},
}
12 changes: 12 additions & 0 deletions apps/sim/tools/onedrive/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import { copyTool } from '@/tools/onedrive/copy'
import { createFolderTool } from '@/tools/onedrive/create_folder'
import { createShareLinkTool } from '@/tools/onedrive/create_share_link'
import { deleteTool } from '@/tools/onedrive/delete'
import { downloadTool } from '@/tools/onedrive/download'
import { getDriveInfoTool } from '@/tools/onedrive/get_drive_info'
import { getItemTool } from '@/tools/onedrive/get_item'
import { listTool } from '@/tools/onedrive/list'
import { moveTool } from '@/tools/onedrive/move'
import { searchTool } from '@/tools/onedrive/search'
import { uploadTool } from '@/tools/onedrive/upload'

export const onedriveCopyTool = copyTool
export const onedriveCreateFolderTool = createFolderTool
export const onedriveCreateShareLinkTool = createShareLinkTool
export const onedriveDeleteTool = deleteTool
export const onedriveDownloadTool = downloadTool
export const onedriveGetDriveInfoTool = getDriveInfoTool
export const onedriveGetItemTool = getItemTool
export const onedriveListTool = listTool
export const onedriveMoveTool = moveTool
export const onedriveSearchTool = searchTool
export const onedriveUploadTool = uploadTool
Loading
Loading