Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 61 additions & 2 deletions apps/docs/content/docs/en/tools/sharepoint.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Sharepoint
description: Read and create pages
description: Work with pages and lists
---

import { BlockInfoCard } from "@/components/ui/block-info-card"
Expand Down Expand Up @@ -61,7 +61,7 @@ In Sim, the SharePoint integration empowers your agents to create and access Sha

## Usage Instructions

Integrate Sharepoint into the workflow. Can read and create pages, and list sites. Requires OAuth.
Integrate SharePoint into the workflow. Read/create pages, list sites, and work with lists (read, create, update items). Requires OAuth.



Expand Down Expand Up @@ -124,6 +124,65 @@ List details of all SharePoint sites
| --------- | ---- | ----------- |
| `site` | object | Information about the current SharePoint site |

### `sharepoint_create_list`

Create a new list in a SharePoint site

#### Input

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `siteId` | string | No | The ID of the SharePoint site \(internal use\) |
| `siteSelector` | string | No | Select the SharePoint site |
| `listDisplayName` | string | Yes | Display name of the list to create |
| `listDescription` | string | No | Description of the list |
| `listTemplate` | string | No | List template name \(e.g., 'genericList'\) |
| `pageContent` | string | No | Optional JSON of columns. Either a top-level array of column definitions or an object with \{ columns: \[...\] \}. |

#### Output

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `list` | object | Created SharePoint list information |

### `sharepoint_get_list`

Get metadata (and optionally columns/items) for a SharePoint list

#### Input

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `siteSelector` | string | No | Select the SharePoint site |
| `siteId` | string | No | The ID of the SharePoint site \(internal use\) |
| `listId` | string | No | The ID of the list to retrieve |

#### Output

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `list` | object | Information about the SharePoint list |

### `sharepoint_update_list`

Update the properties (fields) on a SharePoint list item

#### Input

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `siteSelector` | string | No | Select the SharePoint site |
| `siteId` | string | No | The ID of the SharePoint site \(internal use\) |
| `listId` | string | No | The ID of the list containing the item |
| `itemId` | string | Yes | The ID of the list item to update |
| `listItemFields` | object | Yes | Field values to update on the list item |

#### Output

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `item` | object | Updated SharePoint list item |



## Notes
Expand Down
194 changes: 186 additions & 8 deletions apps/sim/blocks/blocks/sharepoint.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { MicrosoftSharepointIcon } from '@/components/icons'
import { createLogger } from '@/lib/logs/console/logger'
import type { BlockConfig } from '@/blocks/types'
import type { SharepointResponse } from '@/tools/sharepoint/types'

const logger = createLogger('SharepointBlock')

export const SharepointBlock: BlockConfig<SharepointResponse> = {
type: 'sharepoint',
name: 'Sharepoint',
description: 'Read and create pages',
description: 'Work with pages and lists',
longDescription:
'Integrate Sharepoint into the workflow. Can read and create pages, and list sites. Requires OAuth.',
'Integrate SharePoint into the workflow. Read/create pages, list sites, and work with lists (read, create, update items). Requires OAuth.',
docsLink: 'https://docs.sim.ai/tools/sharepoint',
category: 'tools',
bgColor: '#E0E0E0',
Expand All @@ -23,6 +26,9 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
{ label: 'Create Page', id: 'create_page' },
{ label: 'Read Page', id: 'read_page' },
{ label: 'List Sites', id: 'list_sites' },
{ label: 'Create List', id: 'create_list' },
{ label: 'Read List', id: 'read_list' },
{ label: 'Update List', id: 'update_list' },
],
},
// Sharepoint Credentials
Expand All @@ -39,6 +45,8 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
'email',
'Files.Read',
'Files.ReadWrite',
'Sites.Read.All',
'Sites.ReadWrite.All',
'offline_access',
],
placeholder: 'Select Microsoft account',
Expand All @@ -64,7 +72,17 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
placeholder: 'Select a site',
dependsOn: ['credential'],
mode: 'basic',
condition: { field: 'operation', value: ['create_page', 'read_page', 'list_sites'] },
condition: {
field: 'operation',
value: [
'create_page',
'read_page',
'list_sites',
'create_list',
'read_list',
'update_list',
],
},
},

{
Expand All @@ -86,13 +104,59 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
mode: 'advanced',
},

{
id: 'listId',
title: 'List ID',
type: 'short-input',
layout: 'full',
placeholder: 'Enter list ID (GUID). Required for Update; optional for Read.',
canonicalParamId: 'listId',
condition: { field: 'operation', value: ['read_list', 'update_list'] },
},

{
id: 'listItemId',
title: 'Item ID',
type: 'short-input',
layout: 'full',
placeholder: 'Enter item ID',
canonicalParamId: 'itemId',
condition: { field: 'operation', value: ['update_list'] },
},

{
id: 'listDisplayName',
title: 'List Display Name',
type: 'short-input',
layout: 'full',
placeholder: 'Name of the list',
condition: { field: 'operation', value: 'create_list' },
},

{
id: 'listTemplate',
title: 'List Template',
type: 'short-input',
layout: 'full',
placeholder: "Template (e.g., 'genericList')",
condition: { field: 'operation', value: 'create_list' },
},

{
id: 'pageContent',
title: 'Page Content',
type: 'long-input',
layout: 'full',
placeholder: 'Content of the page',
condition: { field: 'operation', value: 'create_page' },
placeholder: 'Provide page content',
condition: { field: 'operation', value: ['create_list'] },
},
{
id: 'listDescription',
title: 'List Description',
type: 'long-input',
layout: 'full',
placeholder: 'Optional description',
condition: { field: 'operation', value: 'create_list' },
},

{
Expand All @@ -106,9 +170,26 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
mode: 'advanced',
condition: { field: 'operation', value: 'create_page' },
},

{
id: 'listItemFields',
title: 'List Item Fields',
type: 'long-input',
layout: 'full',
placeholder: 'Enter list item fields',
canonicalParamId: 'listItemFields',
condition: { field: 'operation', value: 'update_list' },
},
],
tools: {
access: ['sharepoint_create_page', 'sharepoint_read_page', 'sharepoint_list_sites'],
access: [
'sharepoint_create_page',
'sharepoint_read_page',
'sharepoint_list_sites',
'sharepoint_create_list',
'sharepoint_get_list',
'sharepoint_update_list',
],
config: {
tool: (params) => {
switch (params.operation) {
Expand All @@ -118,6 +199,12 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
return 'sharepoint_read_page'
case 'list_sites':
return 'sharepoint_list_sites'
case 'create_list':
return 'sharepoint_create_list'
case 'read_list':
return 'sharepoint_get_list'
case 'update_list':
return 'sharepoint_update_list'
default:
throw new Error(`Invalid Sharepoint operation: ${params.operation}`)
}
Expand All @@ -128,12 +215,71 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
// Use siteSelector if provided, otherwise use manualSiteId
const effectiveSiteId = (siteSelector || manualSiteId || '').trim()

const {
itemId: providedItemId,
listItemId,
listItemFields,
includeColumns,
includeItems,
...others
} = rest as any

let parsedItemFields: any = listItemFields
if (typeof listItemFields === 'string' && listItemFields.trim()) {
try {
parsedItemFields = JSON.parse(listItemFields)
} catch (error) {
logger.error('Failed to parse listItemFields JSON', {
error: error instanceof Error ? error.message : String(error),
})
}
}
// Ensure listItemFields is an object for the tool schema
if (typeof parsedItemFields !== 'object' || parsedItemFields === null) {
parsedItemFields = undefined
}

// Sanitize item ID (required by tool)
const rawItemId = providedItemId ?? listItemId
const sanitizedItemId =
rawItemId === undefined || rawItemId === null
? undefined
: String(rawItemId).trim() || undefined

const coerceBoolean = (value: any) => {
if (typeof value === 'boolean') return value
if (typeof value === 'string') return value.toLowerCase() === 'true'
return undefined
}

// Debug logging for update_list param mapping
if (others.operation === 'update_list') {
try {
logger.info('SharepointBlock update_list param check', {
siteId: effectiveSiteId || undefined,
listId: (others as any)?.listId,
listTitle: (others as any)?.listTitle,
itemId: sanitizedItemId,
hasItemFields: !!parsedItemFields && typeof parsedItemFields === 'object',
itemFieldKeys:
parsedItemFields && typeof parsedItemFields === 'object'
? Object.keys(parsedItemFields)
: [],
})
} catch {}
}

return {
credential,
siteId: effectiveSiteId || undefined,
pageSize: rest.pageSize ? Number.parseInt(rest.pageSize as string, 10) : undefined,
pageSize: others.pageSize ? Number.parseInt(others.pageSize as string, 10) : undefined,
mimeType: mimeType,
...rest,
...others,
// Map to tool param names
itemId: sanitizedItemId,
listItemFields: parsedItemFields,
includeColumns: coerceBoolean(includeColumns),
includeItems: coerceBoolean(includeItems),
}
},
},
Expand All @@ -151,12 +297,44 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
siteSelector: { type: 'string', description: 'Site selector' },
manualSiteId: { type: 'string', description: 'Manual site ID' },
pageSize: { type: 'number', description: 'Results per page' },
// Create List operation inputs
listDisplayName: { type: 'string', description: 'List display name' },
listDescription: { type: 'string', description: 'List description' },
listTemplate: { type: 'string', description: 'List template' },
// Read List operation inputs
listId: { type: 'string', description: 'List ID' },
listTitle: { type: 'string', description: 'List title' },
includeColumns: { type: 'boolean', description: 'Include columns in response' },
includeItems: { type: 'boolean', description: 'Include items in response' },
// Update List Item operation inputs
listItemId: { type: 'string', description: 'List item ID' },
listItemFields: { type: 'string', description: 'List item fields' },
},
outputs: {
sites: {
type: 'json',
description:
'An array of SharePoint site objects, each containing details such as id, name, and more.',
},
list: {
type: 'json',
description: 'SharePoint list object (id, displayName, name, webUrl, etc.)',
},
item: {
type: 'json',
description: 'SharePoint list item with fields',
},
items: {
type: 'json',
description: 'Array of SharePoint list items with fields',
},
success: {
type: 'boolean',
description: 'Success status',
},
error: {
type: 'string',
description: 'Error message',
},
},
}
1 change: 1 addition & 0 deletions apps/sim/lib/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,7 @@ export const auth = betterAuth({
'email',
'Sites.Read.All',
'Sites.ReadWrite.All',
'Sites.Manage.All',
'offline_access',
],
responseType: 'code',
Expand Down
1 change: 1 addition & 0 deletions apps/sim/lib/oauth/oauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
'email',
'Sites.Read.All',
'Sites.ReadWrite.All',
'Sites.Manage.All',
'offline_access',
],
},
Expand Down
Loading