mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-06 03:00:16 -04:00
Improvement(sharepoint): added ability to create list items, different from create list (#1379)
* added add list items (cherry picked from commit df6ea35d5bb975c03c7ec0c787bd915f34890ac0) * bun run lint * minor changes --------- Co-authored-by: Adam Gough <adamgough@Mac.attlocal.net> Co-authored-by: Adam Gough <adamgough@Adams-MacBook-Pro.local>
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
"google_calendar",
|
||||
"google_docs",
|
||||
"google_drive",
|
||||
"google_forms",
|
||||
"google_search",
|
||||
"google_sheets",
|
||||
"huggingface",
|
||||
|
||||
@@ -183,6 +183,25 @@ Update the properties (fields) on a SharePoint list item
|
||||
| --------- | ---- | ----------- |
|
||||
| `item` | object | Updated SharePoint list item |
|
||||
|
||||
### `sharepoint_add_list_items`
|
||||
|
||||
Add a new item to 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 | Yes | The ID of the list to add the item to |
|
||||
| `listItemFields` | object | Yes | Field values for the new list item |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `item` | object | Created SharePoint list item |
|
||||
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
@@ -16,7 +16,6 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
|
||||
bgColor: '#E0E0E0',
|
||||
icon: MicrosoftSharepointIcon,
|
||||
subBlocks: [
|
||||
// Operation selector
|
||||
{
|
||||
id: 'operation',
|
||||
title: 'Operation',
|
||||
@@ -29,9 +28,9 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
|
||||
{ label: 'Create List', id: 'create_list' },
|
||||
{ label: 'Read List', id: 'read_list' },
|
||||
{ label: 'Update List', id: 'update_list' },
|
||||
{ label: 'Add List Items', id: 'add_list_items' },
|
||||
],
|
||||
},
|
||||
// Sharepoint Credentials
|
||||
{
|
||||
id: 'credential',
|
||||
title: 'Microsoft Account',
|
||||
@@ -81,6 +80,7 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
|
||||
'create_list',
|
||||
'read_list',
|
||||
'update_list',
|
||||
'add_list_items',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -111,7 +111,7 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
|
||||
layout: 'full',
|
||||
placeholder: 'Enter list ID (GUID). Required for Update; optional for Read.',
|
||||
canonicalParamId: 'listId',
|
||||
condition: { field: 'operation', value: ['read_list', 'update_list'] },
|
||||
condition: { field: 'operation', value: ['read_list', 'update_list', 'add_list_items'] },
|
||||
},
|
||||
|
||||
{
|
||||
@@ -178,7 +178,7 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
|
||||
layout: 'full',
|
||||
placeholder: 'Enter list item fields',
|
||||
canonicalParamId: 'listItemFields',
|
||||
condition: { field: 'operation', value: 'update_list' },
|
||||
condition: { field: 'operation', value: ['update_list', 'add_list_items'] },
|
||||
},
|
||||
],
|
||||
tools: {
|
||||
@@ -189,6 +189,7 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
|
||||
'sharepoint_create_list',
|
||||
'sharepoint_get_list',
|
||||
'sharepoint_update_list',
|
||||
'sharepoint_add_list_items',
|
||||
],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
@@ -205,6 +206,8 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
|
||||
return 'sharepoint_get_list'
|
||||
case 'update_list':
|
||||
return 'sharepoint_update_list'
|
||||
case 'add_list_items':
|
||||
return 'sharepoint_add_list_items'
|
||||
default:
|
||||
throw new Error(`Invalid Sharepoint operation: ${params.operation}`)
|
||||
}
|
||||
@@ -212,7 +215,6 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
|
||||
params: (params) => {
|
||||
const { credential, siteSelector, manualSiteId, mimeType, ...rest } = params
|
||||
|
||||
// Use siteSelector if provided, otherwise use manualSiteId
|
||||
const effectiveSiteId = (siteSelector || manualSiteId || '').trim()
|
||||
|
||||
const {
|
||||
@@ -234,12 +236,10 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
|
||||
})
|
||||
}
|
||||
}
|
||||
// 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
|
||||
@@ -252,10 +252,9 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
|
||||
return undefined
|
||||
}
|
||||
|
||||
// Debug logging for update_list param mapping
|
||||
if (others.operation === 'update_list') {
|
||||
if (others.operation === 'update_list' || others.operation === 'add_list_items') {
|
||||
try {
|
||||
logger.info('SharepointBlock update_list param check', {
|
||||
logger.info('SharepointBlock list item param check', {
|
||||
siteId: effectiveSiteId || undefined,
|
||||
listId: (others as any)?.listId,
|
||||
listTitle: (others as any)?.listTitle,
|
||||
@@ -275,7 +274,6 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
|
||||
pageSize: others.pageSize ? Number.parseInt(others.pageSize as string, 10) : undefined,
|
||||
mimeType: mimeType,
|
||||
...others,
|
||||
// Map to tool param names
|
||||
itemId: sanitizedItemId,
|
||||
listItemFields: parsedItemFields,
|
||||
includeColumns: coerceBoolean(includeColumns),
|
||||
@@ -287,26 +285,20 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
|
||||
inputs: {
|
||||
operation: { type: 'string', description: 'Operation to perform' },
|
||||
credential: { type: 'string', description: 'Microsoft account credential' },
|
||||
// Create Page operation inputs
|
||||
pageName: { type: 'string', description: 'Page name' },
|
||||
pageContent: { type: 'string', description: 'Page content' },
|
||||
pageTitle: { type: 'string', description: 'Page title' },
|
||||
// Read Page operation inputs
|
||||
pageId: { type: 'string', description: 'Page ID' },
|
||||
// List operation inputs
|
||||
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' },
|
||||
},
|
||||
|
||||
@@ -145,6 +145,7 @@ import { redditGetCommentsTool, redditGetPostsTool, redditHotPostsTool } from '@
|
||||
import { s3GetObjectTool } from '@/tools/s3'
|
||||
import { searchTool as serperSearch } from '@/tools/serper'
|
||||
import {
|
||||
sharepointAddListItemTool,
|
||||
sharepointCreateListTool,
|
||||
sharepointCreatePageTool,
|
||||
sharepointGetListTool,
|
||||
@@ -370,6 +371,7 @@ export const tools: Record<string, ToolConfig> = {
|
||||
sharepoint_get_list: sharepointGetListTool,
|
||||
sharepoint_create_list: sharepointCreateListTool,
|
||||
sharepoint_update_list: sharepointUpdateListItemTool,
|
||||
sharepoint_add_list_items: sharepointAddListItemTool,
|
||||
// Provider chat tools
|
||||
// Provider chat tools - handled separately in agent blocks
|
||||
}
|
||||
|
||||
167
apps/sim/tools/sharepoint/add_list_items.ts
Normal file
167
apps/sim/tools/sharepoint/add_list_items.ts
Normal file
@@ -0,0 +1,167 @@
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import type { SharepointAddListItemResponse, SharepointToolParams } from '@/tools/sharepoint/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
const logger = createLogger('SharePointAddListItem')
|
||||
|
||||
export const addListItemTool: ToolConfig<SharepointToolParams, SharepointAddListItemResponse> = {
|
||||
id: 'sharepoint_add_list_items',
|
||||
name: 'Add SharePoint List Item',
|
||||
description: 'Add a new item to a SharePoint list',
|
||||
version: '1.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'sharepoint',
|
||||
additionalScopes: ['openid', 'profile', 'email', 'Sites.ReadWrite.All', 'offline_access'],
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'The access token for the SharePoint API',
|
||||
},
|
||||
siteSelector: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Select the SharePoint site',
|
||||
},
|
||||
siteId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'hidden',
|
||||
description: 'The ID of the SharePoint site (internal use)',
|
||||
},
|
||||
listId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'The ID of the list to add the item to',
|
||||
},
|
||||
listItemFields: {
|
||||
type: 'object',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Field values for the new list item',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const siteId = params.siteId || params.siteSelector || 'root'
|
||||
if (!params.listId) {
|
||||
throw new Error('listId must be provided')
|
||||
}
|
||||
const listSegment = params.listId
|
||||
return `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${listSegment}/items`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
body: (params) => {
|
||||
if (!params.listItemFields || Object.keys(params.listItemFields).length === 0) {
|
||||
throw new Error('listItemFields must not be empty')
|
||||
}
|
||||
|
||||
const providedFields =
|
||||
typeof params.listItemFields === 'object' &&
|
||||
params.listItemFields !== null &&
|
||||
'fields' in (params.listItemFields as Record<string, unknown>) &&
|
||||
Object.keys(params.listItemFields as Record<string, unknown>).length === 1
|
||||
? ((params.listItemFields as any).fields as Record<string, unknown>)
|
||||
: (params.listItemFields as Record<string, unknown>)
|
||||
|
||||
if (!providedFields || Object.keys(providedFields).length === 0) {
|
||||
throw new Error('No fields provided to create the SharePoint list item')
|
||||
}
|
||||
|
||||
const readOnlyFields = new Set<string>([
|
||||
'Id',
|
||||
'id',
|
||||
'UniqueId',
|
||||
'GUID',
|
||||
'ContentTypeId',
|
||||
'Created',
|
||||
'Modified',
|
||||
'Author',
|
||||
'Editor',
|
||||
'CreatedBy',
|
||||
'ModifiedBy',
|
||||
'AuthorId',
|
||||
'EditorId',
|
||||
'_UIVersionString',
|
||||
'Attachments',
|
||||
'FileRef',
|
||||
'FileDirRef',
|
||||
'FileLeafRef',
|
||||
])
|
||||
|
||||
const entries = Object.entries(providedFields)
|
||||
const creatableEntries = entries.filter(([key]) => !readOnlyFields.has(key))
|
||||
|
||||
if (creatableEntries.length !== entries.length) {
|
||||
const removed = entries.filter(([key]) => readOnlyFields.has(key)).map(([key]) => key)
|
||||
logger.warn('Removed read-only SharePoint fields from create', {
|
||||
removed,
|
||||
})
|
||||
}
|
||||
|
||||
if (creatableEntries.length === 0) {
|
||||
const requestedKeys = Object.keys(providedFields)
|
||||
throw new Error(
|
||||
`All provided fields are read-only and cannot be set: ${requestedKeys.join(', ')}`
|
||||
)
|
||||
}
|
||||
|
||||
const sanitizedFields = Object.fromEntries(creatableEntries)
|
||||
|
||||
logger.info('Creating SharePoint list item', {
|
||||
listId: params.listId,
|
||||
fieldsKeys: Object.keys(sanitizedFields),
|
||||
})
|
||||
|
||||
return {
|
||||
fields: sanitizedFields,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params) => {
|
||||
let data: any
|
||||
try {
|
||||
data = await response.json()
|
||||
} catch {
|
||||
data = undefined
|
||||
}
|
||||
|
||||
const itemId: string | undefined = data?.id
|
||||
const fields: Record<string, unknown> | undefined = data?.fields || params?.listItemFields
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
item: {
|
||||
id: itemId || 'unknown',
|
||||
fields,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
item: {
|
||||
type: 'object',
|
||||
description: 'Created SharePoint list item',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Item ID' },
|
||||
fields: { type: 'object', description: 'Field values for the new item' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { addListItemTool } from '@/tools/sharepoint/add_list_items'
|
||||
import { createListTool } from '@/tools/sharepoint/create_list'
|
||||
import { createPageTool } from '@/tools/sharepoint/create_page'
|
||||
import { getListTool } from '@/tools/sharepoint/get_list'
|
||||
@@ -11,3 +12,4 @@ export const sharepointGetListTool = getListTool
|
||||
export const sharepointListSitesTool = listSitesTool
|
||||
export const sharepointReadPageTool = readPageTool
|
||||
export const sharepointUpdateListItemTool = updateListItemTool
|
||||
export const sharepointAddListItemTool = addListItemTool
|
||||
|
||||
@@ -259,6 +259,7 @@ export type SharepointResponse =
|
||||
| SharepointGetListResponse
|
||||
| SharepointCreateListResponse
|
||||
| SharepointUpdateListItemResponse
|
||||
| SharepointAddListItemResponse
|
||||
|
||||
export interface SharepointGetListResponse extends ToolResponse {
|
||||
output: {
|
||||
@@ -282,3 +283,12 @@ export interface SharepointUpdateListItemResponse extends ToolResponse {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface SharepointAddListItemResponse extends ToolResponse {
|
||||
output: {
|
||||
item: {
|
||||
id: string
|
||||
fields?: Record<string, unknown>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user