Skip to content

Commit ddb5c93

Browse files
Adam GoughAdam Gough
authored andcommitted
added add list items
(cherry picked from commit df6ea35)
1 parent 3905d1c commit ddb5c93

5 files changed

Lines changed: 202 additions & 5 deletions

File tree

apps/sim/blocks/blocks/sharepoint.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
2929
{ label: 'Create List', id: 'create_list' },
3030
{ label: 'Read List', id: 'read_list' },
3131
{ label: 'Update List', id: 'update_list' },
32+
{ label: 'Add List Items', id: 'add_list_items' },
3233
],
3334
},
3435
// Sharepoint Credentials
@@ -81,6 +82,7 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
8182
'create_list',
8283
'read_list',
8384
'update_list',
85+
'add_list_items',
8486
],
8587
},
8688
},
@@ -111,7 +113,7 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
111113
layout: 'full',
112114
placeholder: 'Enter list ID (GUID). Required for Update; optional for Read.',
113115
canonicalParamId: 'listId',
114-
condition: { field: 'operation', value: ['read_list', 'update_list'] },
116+
condition: { field: 'operation', value: ['read_list', 'update_list', 'add_list_items'] },
115117
},
116118

117119
{
@@ -178,7 +180,7 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
178180
layout: 'full',
179181
placeholder: 'Enter list item fields',
180182
canonicalParamId: 'listItemFields',
181-
condition: { field: 'operation', value: 'update_list' },
183+
condition: { field: 'operation', value: ['update_list', 'add_list_items'] },
182184
},
183185
],
184186
tools: {
@@ -189,6 +191,7 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
189191
'sharepoint_create_list',
190192
'sharepoint_get_list',
191193
'sharepoint_update_list',
194+
'sharepoint_add_list_items',
192195
],
193196
config: {
194197
tool: (params) => {
@@ -205,6 +208,8 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
205208
return 'sharepoint_get_list'
206209
case 'update_list':
207210
return 'sharepoint_update_list'
211+
case 'add_list_items':
212+
return 'sharepoint_add_list_items'
208213
default:
209214
throw new Error(`Invalid Sharepoint operation: ${params.operation}`)
210215
}
@@ -252,10 +257,10 @@ export const SharepointBlock: BlockConfig<SharepointResponse> = {
252257
return undefined
253258
}
254259

255-
// Debug logging for update_list param mapping
256-
if (others.operation === 'update_list') {
260+
// Debug logging for update_list/add_list_items param mapping
261+
if (others.operation === 'update_list' || others.operation === 'add_list_items') {
257262
try {
258-
logger.info('SharepointBlock update_list param check', {
263+
logger.info('SharepointBlock list item param check', {
259264
siteId: effectiveSiteId || undefined,
260265
listId: (others as any)?.listId,
261266
listTitle: (others as any)?.listTitle,

apps/sim/tools/registry.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ import {
151151
sharepointListSitesTool,
152152
sharepointReadPageTool,
153153
sharepointUpdateListItemTool,
154+
sharepointAddListItemTool,
154155
} from '@/tools/sharepoint'
155156
import { slackCanvasTool, slackMessageReaderTool, slackMessageTool } from '@/tools/slack'
156157
import { smsSendTool } from '@/tools/sms'
@@ -370,6 +371,7 @@ export const tools: Record<string, ToolConfig> = {
370371
sharepoint_get_list: sharepointGetListTool,
371372
sharepoint_create_list: sharepointCreateListTool,
372373
sharepoint_update_list: sharepointUpdateListItemTool,
374+
sharepoint_add_list_items: sharepointAddListItemTool,
373375
// Provider chat tools
374376
// Provider chat tools - handled separately in agent blocks
375377
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
import { createLogger } from '@/lib/logs/console/logger'
2+
import type {
3+
SharepointToolParams,
4+
SharepointAddListItemResponse,
5+
} from '@/tools/sharepoint/types'
6+
import type { ToolConfig } from '@/tools/types'
7+
8+
const logger = createLogger('SharePointAddListItem')
9+
10+
export const addListItemTool: ToolConfig<
11+
SharepointToolParams,
12+
SharepointAddListItemResponse
13+
> = {
14+
id: 'sharepoint_add_list_items',
15+
name: 'Add SharePoint List Item',
16+
description: 'Add a new item to a SharePoint list',
17+
version: '1.0',
18+
19+
oauth: {
20+
required: true,
21+
provider: 'sharepoint',
22+
additionalScopes: ['openid', 'profile', 'email', 'Sites.ReadWrite.All', 'offline_access'],
23+
},
24+
25+
params: {
26+
accessToken: {
27+
type: 'string',
28+
required: true,
29+
visibility: 'hidden',
30+
description: 'The access token for the SharePoint API',
31+
},
32+
siteSelector: {
33+
type: 'string',
34+
required: false,
35+
visibility: 'user-only',
36+
description: 'Select the SharePoint site',
37+
},
38+
siteId: {
39+
type: 'string',
40+
required: false,
41+
visibility: 'hidden',
42+
description: 'The ID of the SharePoint site (internal use)',
43+
},
44+
listId: {
45+
type: 'string',
46+
required: true,
47+
visibility: 'user-only',
48+
description: 'The ID of the list to add the item to',
49+
},
50+
listItemFields: {
51+
type: 'object',
52+
required: true,
53+
visibility: 'user-only',
54+
description: 'Field values for the new list item',
55+
},
56+
},
57+
58+
request: {
59+
url: (params) => {
60+
const siteId = params.siteId || params.siteSelector || 'root'
61+
if (!params.listId) {
62+
throw new Error('listId must be provided')
63+
}
64+
const listSegment = params.listId
65+
return `https://graph.microsoft.com/v1.0/sites/${siteId}/lists/${listSegment}/items`
66+
},
67+
method: 'POST',
68+
headers: (params) => ({
69+
Authorization: `Bearer ${params.accessToken}`,
70+
'Content-Type': 'application/json',
71+
Accept: 'application/json',
72+
}),
73+
body: (params) => {
74+
if (!params.listItemFields || Object.keys(params.listItemFields).length === 0) {
75+
throw new Error('listItemFields must not be empty')
76+
}
77+
78+
// Support both { fields: {...} } and raw { fieldName: value } inputs
79+
const providedFields =
80+
typeof params.listItemFields === 'object' &&
81+
params.listItemFields !== null &&
82+
'fields' in (params.listItemFields as Record<string, unknown>) &&
83+
Object.keys(params.listItemFields as Record<string, unknown>).length === 1
84+
? ((params.listItemFields as any).fields as Record<string, unknown>)
85+
: (params.listItemFields as Record<string, unknown>)
86+
87+
if (!providedFields || Object.keys(providedFields).length === 0) {
88+
throw new Error('No fields provided to create the SharePoint list item')
89+
}
90+
91+
// Filter out system/read-only fields that cannot be set via Graph
92+
const readOnlyFields = new Set<string>([
93+
'Id',
94+
'id',
95+
'UniqueId',
96+
'GUID',
97+
'ContentTypeId',
98+
'Created',
99+
'Modified',
100+
'Author',
101+
'Editor',
102+
'CreatedBy',
103+
'ModifiedBy',
104+
'AuthorId',
105+
'EditorId',
106+
'_UIVersionString',
107+
'Attachments',
108+
'FileRef',
109+
'FileDirRef',
110+
'FileLeafRef',
111+
])
112+
113+
const entries = Object.entries(providedFields)
114+
const creatableEntries = entries.filter(([key]) => !readOnlyFields.has(key))
115+
116+
if (creatableEntries.length !== entries.length) {
117+
const removed = entries.filter(([key]) => readOnlyFields.has(key)).map(([key]) => key)
118+
logger.warn('Removed read-only SharePoint fields from create', {
119+
removed,
120+
})
121+
}
122+
123+
if (creatableEntries.length === 0) {
124+
const requestedKeys = Object.keys(providedFields)
125+
throw new Error(
126+
`All provided fields are read-only and cannot be set: ${requestedKeys.join(', ')}`
127+
)
128+
}
129+
130+
const sanitizedFields = Object.fromEntries(creatableEntries)
131+
132+
logger.info('Creating SharePoint list item', {
133+
listId: params.listId,
134+
fieldsKeys: Object.keys(sanitizedFields),
135+
})
136+
137+
return {
138+
fields: sanitizedFields,
139+
}
140+
},
141+
},
142+
143+
transformResponse: async (response: Response, params) => {
144+
let data: any = undefined
145+
try {
146+
data = await response.json()
147+
} catch {
148+
// Some Graph endpoints may not return a body consistently
149+
data = undefined
150+
}
151+
152+
const itemId: string | undefined = data?.id
153+
const fields: Record<string, unknown> | undefined = data?.fields || params?.listItemFields
154+
155+
return {
156+
success: true,
157+
output: {
158+
item: {
159+
id: itemId || 'unknown',
160+
fields,
161+
},
162+
},
163+
}
164+
},
165+
166+
outputs: {
167+
item: {
168+
type: 'object',
169+
description: 'Created SharePoint list item',
170+
properties: {
171+
id: { type: 'string', description: 'Item ID' },
172+
fields: { type: 'object', description: 'Field values for the new item' },
173+
},
174+
},
175+
},
176+
}
177+
178+

apps/sim/tools/sharepoint/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import { getListTool } from '@/tools/sharepoint/get_list'
44
import { listSitesTool } from '@/tools/sharepoint/list_sites'
55
import { readPageTool } from '@/tools/sharepoint/read_page'
66
import { updateListItemTool } from '@/tools/sharepoint/update_list'
7+
import { addListItemTool } from '@/tools/sharepoint/add_list_items'
78

89
export const sharepointCreatePageTool = createPageTool
910
export const sharepointCreateListTool = createListTool
1011
export const sharepointGetListTool = getListTool
1112
export const sharepointListSitesTool = listSitesTool
1213
export const sharepointReadPageTool = readPageTool
1314
export const sharepointUpdateListItemTool = updateListItemTool
15+
export const sharepointAddListItemTool = addListItemTool

apps/sim/tools/sharepoint/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ export type SharepointResponse =
259259
| SharepointGetListResponse
260260
| SharepointCreateListResponse
261261
| SharepointUpdateListItemResponse
262+
| SharepointAddListItemResponse
262263

263264
export interface SharepointGetListResponse extends ToolResponse {
264265
output: {
@@ -282,3 +283,12 @@ export interface SharepointUpdateListItemResponse extends ToolResponse {
282283
}
283284
}
284285
}
286+
287+
export interface SharepointAddListItemResponse extends ToolResponse {
288+
output: {
289+
item: {
290+
id: string
291+
fields?: Record<string, unknown>
292+
}
293+
}
294+
}

0 commit comments

Comments
 (0)