From e9004cb7158a1d78bf6b6faccb90aae66e75cf89 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 6 May 2026 12:43:01 -0700 Subject: [PATCH 1/2] fix(office-excel): support Office.js add-in embed and surface Graph errors --- .../api/tools/microsoft_excel/drives/route.ts | 20 +--- .../api/tools/microsoft_excel/sheets/route.ts | 14 +-- .../chat/[identifier]/office-embed-init.tsx | 50 +++++++++ apps/sim/app/chat/[identifier]/page.tsx | 19 +++- apps/sim/lib/core/security/csp.test.ts | 19 ++++ apps/sim/lib/core/security/csp.ts | 15 ++- apps/sim/tools/error-extractors.ts | 48 ++++++++ apps/sim/tools/microsoft_excel/read.ts | 18 ++- apps/sim/tools/microsoft_excel/table_add.ts | 2 + apps/sim/tools/microsoft_excel/utils.test.ts | 90 +++++++++++++++ apps/sim/tools/microsoft_excel/utils.ts | 106 ++++++++++++++++++ .../tools/microsoft_excel/worksheet_add.ts | 15 +-- apps/sim/tools/microsoft_excel/write.ts | 18 +++ 13 files changed, 392 insertions(+), 42 deletions(-) create mode 100644 apps/sim/app/chat/[identifier]/office-embed-init.tsx create mode 100644 apps/sim/tools/microsoft_excel/utils.test.ts diff --git a/apps/sim/app/api/tools/microsoft_excel/drives/route.ts b/apps/sim/app/api/tools/microsoft_excel/drives/route.ts index df884bea928..2e0d1d80e43 100644 --- a/apps/sim/app/api/tools/microsoft_excel/drives/route.ts +++ b/apps/sim/app/api/tools/microsoft_excel/drives/route.ts @@ -7,7 +7,7 @@ import { validatePathSegment, validateSharePointSiteId } from '@/lib/core/securi import { generateRequestId } from '@/lib/core/utils/request' import { withRouteHandler } from '@/lib/core/utils/with-route-handler' import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils' -import { GRAPH_ID_PATTERN } from '@/tools/microsoft_excel/utils' +import { extractGraphError, GRAPH_ID_PATTERN } from '@/tools/microsoft_excel/utils' export const dynamic = 'force-dynamic' @@ -76,13 +76,8 @@ export const POST = withRouteHandler(async (request: NextRequest) => { }) if (!response.ok) { - const errorData = await response - .json() - .catch(() => ({ error: { message: 'Unknown error' } })) - return NextResponse.json( - { error: errorData.error?.message || 'Failed to fetch drive' }, - { status: response.status } - ) + const errorMessage = await extractGraphError(response) + return NextResponse.json({ error: errorMessage }, { status: response.status }) } const data: GraphDrive = await response.json() @@ -102,15 +97,12 @@ export const POST = withRouteHandler(async (request: NextRequest) => { }) if (!response.ok) { - const errorData = await response.json().catch(() => ({ error: { message: 'Unknown error' } })) + const errorMessage = await extractGraphError(response) logger.error(`[${requestId}] Microsoft Graph API error fetching drives`, { status: response.status, - error: errorData.error?.message, + error: errorMessage, }) - return NextResponse.json( - { error: errorData.error?.message || 'Failed to fetch drives' }, - { status: response.status } - ) + return NextResponse.json({ error: errorMessage }, { status: response.status }) } const data = await response.json() diff --git a/apps/sim/app/api/tools/microsoft_excel/sheets/route.ts b/apps/sim/app/api/tools/microsoft_excel/sheets/route.ts index 7a2c64cf6c3..19212aaa59a 100644 --- a/apps/sim/app/api/tools/microsoft_excel/sheets/route.ts +++ b/apps/sim/app/api/tools/microsoft_excel/sheets/route.ts @@ -6,7 +6,7 @@ import { authorizeCredentialUse } from '@/lib/auth/credential-access' import { generateRequestId } from '@/lib/core/utils/request' import { withRouteHandler } from '@/lib/core/utils/with-route-handler' import { refreshAccessTokenIfNeeded } from '@/app/api/auth/oauth/utils' -import { getItemBasePath } from '@/tools/microsoft_excel/utils' +import { extractGraphError, getItemBasePath } from '@/tools/microsoft_excel/utils' export const dynamic = 'force-dynamic' @@ -73,18 +73,12 @@ export const GET = withRouteHandler(async (request: NextRequest) => { }) if (!worksheetsResponse.ok) { - const errorData = await worksheetsResponse - .text() - .then((text) => JSON.parse(text)) - .catch(() => ({ error: { message: 'Unknown error' } })) + const errorMessage = await extractGraphError(worksheetsResponse) logger.error(`[${requestId}] Microsoft Graph API error`, { status: worksheetsResponse.status, - error: errorData.error?.message || 'Failed to fetch worksheets', + error: errorMessage, }) - return NextResponse.json( - { error: errorData.error?.message || 'Failed to fetch worksheets' }, - { status: worksheetsResponse.status } - ) + return NextResponse.json({ error: errorMessage }, { status: worksheetsResponse.status }) } const data: WorksheetsResponse = await worksheetsResponse.json() diff --git a/apps/sim/app/chat/[identifier]/office-embed-init.tsx b/apps/sim/app/chat/[identifier]/office-embed-init.tsx new file mode 100644 index 00000000000..02729d65274 --- /dev/null +++ b/apps/sim/app/chat/[identifier]/office-embed-init.tsx @@ -0,0 +1,50 @@ +'use client' + +import Script from 'next/script' + +declare global { + interface Window { + Office?: { + onReady: () => Promise<{ host: string | null; platform: string | null }> + } + } +} + +/** + * Office.js nullifies window.history.replaceState and pushState (a legacy + * IE10 workaround inside the library) which breaks Next.js's client-side + * router. Cache the originals at module load — before