import type { Result } from '../../domain/result.js'; import type { GraphClient, GraphError } from '../../infra/graph-client.js'; /** * Helpers that consolidate the "Graph hands you a 302, follow the CDN * redirect, return the bytes" dance used by every command that needs * raw file content. * * Real Graph responses for `/drives/{id}/items/{id}/content` (and the * `?format=pdf` / `?format=html` variants) are 302 redirects to a CDN URL. * `getBinary` captures the redirect and returns * `{ '@microsoft.graph.downloadUrl': '...' }` — NOT inline bytes. To get * the bytes we have to follow the URL via `fetchUrl`, which is host-allow- * listed for SharePoint / ODSP / Microsoft media-transform domains. * * Two shapes for the return value depending on what the caller needs: * - `fetchRawBytes(graph, path, opts)` → `Uint8Array` for local * conversion (mammoth / sheetjs / turndown). * - `inlineBinary(graph, path, opts)` → `{ contentType, size, base64 }` * for "stream the bytes back through the JSON envelope" workflows * (PDF conversion, image attachments, anything the LLM consumer * either pipes to disk or saves via --output-path). * * The historical-version commands pass `elevated: true` so that the * initial Graph call is signed with an M365ChatClient token (on the * ODSP `logicalPermissions` allow-list); without that, Graph's 302 * redirects to a streamContent URL whose embedded tempauth is signed * by Teams web client identity and rejected by SharePoint with 403. */ export type FetchOptions = { readonly elevated?: boolean; }; export type InlineBinary = { readonly contentType: string; readonly size: number; readonly base64: string; }; export declare const fetchRawBytes: (graph: GraphClient, contentPath: string, opts?: FetchOptions) => Promise>; export declare const inlineBinary: (graph: GraphClient, contentPath: string, opts?: FetchOptions) => Promise>; /** * Detect Graph's silent-raw-bytes fallback on `?format=pdf` requests. * * When `format=pdf` succeeds, the response contentType is `application/pdf`. * For some inputs (notably historical-version pptx on certain tenants, or * reference-attachment edge cases) Graph silently falls back to returning * the raw source bytes — same envelope shape, but contentType is the * source MIME (or `application/octet-stream`). The audit (round-5 #2) * caught this happening on `download-drive-item-version --format pdf` for v79 * of a pptx: the response said `contentType: "application/octet-stream"` * with the exact source byte size, and an LLM that saved it as `.pdf` * would have had a corrupt file. * * Tag the result with `passthrough: true` and a sharp note so the LLM * knows the conversion didn't run and saves the bytes with the source * extension instead of `.pdf`. */ export declare const tagPdfPassthrough: (result: Result, sourceLabel: string) => Result;