fix(microsoft-excel): clean up dead code found during integration audit (#5454)

* fix(microsoft-excel): clean up dead code found during integration audit

- Remove unreachable 'update' operation subblocks (Google Sheets
  copy-paste leftover — never a selectable dropdown option and not
  handled by the tool selector or any registered tool)
- Fix microsoft_excel_table_add to trim spreadsheetId and OData-escape
  tableName, matching every other tool in this file
- Drop phantom/dead type fields: Google-Sheets-only insertDataOption
  and responseValueRenderOption (never used), never-populated
  sheetId/sheetName/title/sheets metadata fields, unused rowIndex, and
  the unconfigurable majorDimension param (hardcoded to 'ROWS' now
  that it's inlined)

* fix(microsoft-excel): fix write output field mapping + OData escaping gaps

Found in an independent second-pass audit against the live Graph API
docs:

- microsoft_excel_write (v1) transformResponse read
  updatedRange/updatedRows/updatedColumns/updatedCells from the Graph
  response — none of these fields exist on the workbookRange resource
  (the real fields are address/rowCount/columnCount), so these four
  output fields were always undefined. Fixed to read the actual
  fields, matching what the v2 write tool already does correctly.
- read.ts and write.ts (v1 and v2) built worksheets('name') OData
  URLs with only encodeURIComponent, skipping escapeODataString — a
  worksheet name containing an apostrophe would produce a malformed
  request. Every other tool in this integration already escapes
  correctly; read/write were the outliers.
- write.ts (v1) also wasn't trimming spreadsheetId before use,
  inconsistent with every other tool here.
This commit is contained in:
Waleed
2026-07-06 18:07:52 -07:00
committed by GitHub
parent fb3f95d5dc
commit 03478cd574
5 changed files with 48 additions and 72 deletions
-35
View File
@@ -234,41 +234,6 @@ Return ONLY the JSON array - no explanations, no markdown, no extra text.`,
],
condition: { field: 'operation', value: 'write' },
},
{
id: 'values',
title: 'Values',
type: 'long-input',
placeholder:
'Enter values as JSON array of arrays (e.g., [["A1", "B1"], ["A2", "B2"]]) or an array of objects (e.g., [{"name":"John", "age":30}, {"name":"Jane", "age":25}])',
condition: { field: 'operation', value: 'update' },
required: true,
wandConfig: {
enabled: true,
prompt: `Generate Microsoft Excel data as a JSON array based on the user's description.
Format options:
1. Array of arrays: [["Header1", "Header2"], ["Value1", "Value2"]]
2. Array of objects: [{"column1": "value1", "column2": "value2"}]
Examples:
- "update with new prices" -> [["Product", "Price"], ["Widget A", 29.99], ["Widget B", 49.99]]
- "quarterly targets" -> [{"Q1": 10000, "Q2": 12000, "Q3": 15000, "Q4": 18000}]
Return ONLY the JSON array - no explanations, no markdown, no extra text.`,
placeholder: 'Describe the data you want to update...',
generationType: 'json-object',
},
},
{
id: 'valueInputOption',
title: 'Value Input Option',
type: 'dropdown',
options: [
{ label: 'User Entered (Parse formulas)', id: 'USER_ENTERED' },
{ label: "Raw (Don't parse formulas)", id: 'RAW' },
],
condition: { field: 'operation', value: 'update' },
},
{
id: 'values',
title: 'Values',
+5 -4
View File
@@ -7,6 +7,7 @@ import type {
MicrosoftExcelV2ToolParams,
} from '@/tools/microsoft_excel/types'
import {
escapeODataString,
getItemBasePath,
getSpreadsheetWebUrl,
parseGraphErrorMessage,
@@ -79,7 +80,7 @@ export const readTool: ToolConfig<MicrosoftExcelToolParams, MicrosoftExcelReadRe
const rangeInput = params.range.trim()
if (!rangeInput.includes('!')) {
const sheetOnly = encodeURIComponent(rangeInput)
const sheetOnly = encodeURIComponent(escapeODataString(rangeInput))
return `${basePath}/workbook/worksheets('${sheetOnly}')/usedRange(valuesOnly=true)`
}
@@ -91,7 +92,7 @@ export const readTool: ToolConfig<MicrosoftExcelToolParams, MicrosoftExcelReadRe
)
}
const sheetName = encodeURIComponent(match[1])
const sheetName = encodeURIComponent(escapeODataString(match[1]))
const address = encodeURIComponent(match[2])
return `${basePath}/workbook/worksheets('${sheetName}')/range(address='${address}')`
@@ -128,7 +129,7 @@ export const readTool: ToolConfig<MicrosoftExcelToolParams, MicrosoftExcelReadRe
}
const basePath = getItemBasePath(spreadsheetId, driveId)
const rangeUrl = `${basePath}/workbook/worksheets('${encodeURIComponent(firstSheetName)}')/usedRange(valuesOnly=true)`
const rangeUrl = `${basePath}/workbook/worksheets('${encodeURIComponent(escapeODataString(firstSheetName))}')/usedRange(valuesOnly=true)`
const rangeResp = await fetch(rangeUrl, {
headers: { Authorization: `Bearer ${accessToken}` },
@@ -278,7 +279,7 @@ export const readV2Tool: ToolConfig<MicrosoftExcelV2ToolParams, MicrosoftExcelV2
}
const basePath = getItemBasePath(spreadsheetId, params.driveId)
const encodedSheetName = encodeURIComponent(sheetName)
const encodedSheetName = encodeURIComponent(escapeODataString(sheetName))
if (!params.cellRange) {
return `${basePath}/workbook/worksheets('${encodedSheetName}')/usedRange(valuesOnly=true)`
+24 -8
View File
@@ -3,7 +3,11 @@ import type {
MicrosoftExcelTableAddResponse,
MicrosoftExcelTableToolParams,
} from '@/tools/microsoft_excel/types'
import { getItemBasePath, getSpreadsheetWebUrl } from '@/tools/microsoft_excel/utils'
import {
escapeODataString,
getItemBasePath,
getSpreadsheetWebUrl,
} from '@/tools/microsoft_excel/utils'
import type { ToolConfig } from '@/tools/types'
export const tableAddTool: ToolConfig<
@@ -59,15 +63,27 @@ export const tableAddTool: ToolConfig<
request: {
url: (params) => {
const tableName = encodeURIComponent(params.tableName)
const basePath = getItemBasePath(params.spreadsheetId, params.driveId)
return `${basePath}/workbook/tables('${tableName}')/rows/add`
const spreadsheetId = params.spreadsheetId?.trim()
if (!spreadsheetId) {
throw new Error('Spreadsheet ID is required')
}
const tableName = params.tableName?.trim()
if (!tableName) {
throw new Error('Table name is required')
}
const basePath = getItemBasePath(spreadsheetId, params.driveId)
return `${basePath}/workbook/tables('${encodeURIComponent(escapeODataString(tableName))}')/rows/add`
},
method: 'POST',
headers: (params) => ({
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
}),
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
}
},
body: (params) => {
let processedValues: any = params.values || []
-15
View File
@@ -4,8 +4,6 @@ import type { ToolResponse } from '@/tools/types'
export type ExcelCellValue = string | number | boolean | null
interface MicrosoftExcelRange {
sheetId?: number
sheetName?: string
range: string
values: ExcelCellValue[][]
}
@@ -13,14 +11,6 @@ interface MicrosoftExcelRange {
interface MicrosoftExcelMetadata {
spreadsheetId: string
spreadsheetUrl?: string
title?: string
sheets?: {
sheetId: number
title: string
index: number
rowCount?: number
columnCount?: number
}[]
}
export interface MicrosoftExcelReadResponse extends ToolResponse {
@@ -67,10 +57,7 @@ export interface MicrosoftExcelToolParams {
range?: string
values?: ExcelCellValue[][]
valueInputOption?: 'RAW' | 'USER_ENTERED'
insertDataOption?: 'OVERWRITE' | 'INSERT_ROWS'
includeValuesInResponse?: boolean
responseValueRenderOption?: 'FORMATTED_VALUE' | 'UNFORMATTED_VALUE' | 'FORMULA'
majorDimension?: 'ROWS' | 'COLUMNS'
}
export interface MicrosoftExcelTableToolParams {
@@ -79,7 +66,6 @@ export interface MicrosoftExcelTableToolParams {
driveId?: string
tableName: string
values: ExcelCellValue[][]
rowIndex?: number
}
export interface MicrosoftExcelWorksheetToolParams {
@@ -217,7 +203,6 @@ export interface MicrosoftExcelV2ToolParams {
values?: ExcelCellValue[][]
valueInputOption?: 'RAW' | 'USER_ENTERED'
includeValuesInResponse?: boolean
majorDimension?: 'ROWS' | 'COLUMNS'
}
export interface MicrosoftExcelV2ReadResponse extends ToolResponse {
+19 -10
View File
@@ -5,7 +5,11 @@ import type {
MicrosoftExcelV2WriteResponse,
MicrosoftExcelWriteResponse,
} from '@/tools/microsoft_excel/types'
import { getItemBasePath, getSpreadsheetWebUrl } from '@/tools/microsoft_excel/utils'
import {
escapeODataString,
getItemBasePath,
getSpreadsheetWebUrl,
} from '@/tools/microsoft_excel/utils'
import type { ToolConfig } from '@/tools/types'
/**
@@ -82,6 +86,11 @@ export const writeTool: ToolConfig<MicrosoftExcelToolParams, MicrosoftExcelWrite
request: {
url: (params) => {
const spreadsheetId = params.spreadsheetId?.trim()
if (!spreadsheetId) {
throw new Error('Spreadsheet ID is required')
}
const rangeInput = params.range?.trim()
const match = rangeInput?.match(/^([^!]+)!(.+)$/)
@@ -89,10 +98,10 @@ export const writeTool: ToolConfig<MicrosoftExcelToolParams, MicrosoftExcelWrite
throw new Error(`Invalid range format: "${params.range}". Use the format "Sheet1!A1:B2"`)
}
const sheetName = encodeURIComponent(match[1])
const sheetName = encodeURIComponent(escapeODataString(match[1]))
const address = encodeURIComponent(match[2])
const basePath = getItemBasePath(params.spreadsheetId!, params.driveId)
const basePath = getItemBasePath(spreadsheetId, params.driveId)
const url = new URL(
`${basePath}/workbook/worksheets('${sheetName}')/range(address='${address}')`
)
@@ -145,7 +154,7 @@ export const writeTool: ToolConfig<MicrosoftExcelToolParams, MicrosoftExcelWrite
}
const body: Record<string, any> = {
majorDimension: params.majorDimension || 'ROWS',
majorDimension: 'ROWS',
values: processedValues,
}
@@ -173,10 +182,10 @@ export const writeTool: ToolConfig<MicrosoftExcelToolParams, MicrosoftExcelWrite
return {
success: true,
output: {
updatedRange: data.updatedRange,
updatedRows: data.updatedRows,
updatedColumns: data.updatedColumns,
updatedCells: data.updatedCells,
updatedRange: data.address ?? '',
updatedRows: data.rowCount ?? 0,
updatedColumns: data.columnCount ?? 0,
updatedCells: (data.rowCount ?? 0) * (data.columnCount ?? 0),
metadata: {
spreadsheetId,
spreadsheetUrl: webUrl,
@@ -280,7 +289,7 @@ export const writeV2Tool: ToolConfig<MicrosoftExcelV2ToolParams, MicrosoftExcelV
}
const cellRange = params.cellRange?.trim() || 'A1'
const encodedSheetName = encodeURIComponent(sheetName)
const encodedSheetName = encodeURIComponent(escapeODataString(sheetName))
const encodedAddress = encodeURIComponent(cellRange)
const basePath = getItemBasePath(spreadsheetId, params.driveId)
@@ -337,7 +346,7 @@ export const writeV2Tool: ToolConfig<MicrosoftExcelV2ToolParams, MicrosoftExcelV
}
const body: Record<string, any> = {
majorDimension: params.majorDimension || 'ROWS',
majorDimension: 'ROWS',
values: processedValues,
}