Spaces:
Sleeping
Sleeping
File size: 5,591 Bytes
7dc28be | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | import type { FastMCP } from 'fastmcp';
import { UserError } from 'fastmcp';
import { getDocsClient } from '../../../clients.js';
import {
ApplyParagraphStyleToolParameters,
ApplyParagraphStyleToolArgs,
NotImplementedError,
} from '../../../types.js';
import * as GDocsHelpers from '../../../googleDocsApiHelpers.js';
export function register(server: FastMCP) {
server.addTool({
name: 'applyParagraphStyle',
description:
'Applies paragraph-level formatting (alignment, spacing, heading styles) to paragraphs identified by a character range or by searching for text. Use namedStyleType to set heading levels (HEADING_1 through HEADING_6).',
parameters: ApplyParagraphStyleToolParameters,
execute: async (args: ApplyParagraphStyleToolArgs, { log }) => {
const docs = await getDocsClient();
let startIndex: number | undefined;
let endIndex: number | undefined;
log.info(
`Applying paragraph style to document ${args.documentId}${args.tabId ? ` (tab: ${args.tabId})` : ''}`
);
log.info(`Style options: ${JSON.stringify(args.style)}`);
log.info(`Target specification: ${JSON.stringify(args.target)}`);
try {
// STEP 1: Determine the target paragraph's range based on the targeting method
if ('textToFind' in args.target) {
// Find the text first
log.info(
`Finding text "${args.target.textToFind}" (instance ${args.target.matchInstance || 1})${args.tabId ? ` in tab ${args.tabId}` : ''}`
);
const textRange = await GDocsHelpers.findTextRange(
docs,
args.documentId,
args.target.textToFind,
args.target.matchInstance || 1,
args.tabId
);
if (!textRange) {
throw new UserError(
`Could not find "${args.target.textToFind}" in the document${args.tabId ? ` (tab: ${args.tabId})` : ''}.`
);
}
log.info(
`Found text at range ${textRange.startIndex}-${textRange.endIndex}, now locating containing paragraph`
);
// Then find the paragraph containing this text
const paragraphRange = await GDocsHelpers.getParagraphRange(
docs,
args.documentId,
textRange.startIndex,
args.tabId
);
if (!paragraphRange) {
throw new UserError(`Found the text but could not determine the paragraph boundaries.`);
}
startIndex = paragraphRange.startIndex;
endIndex = paragraphRange.endIndex;
log.info(`Text is contained within paragraph at range ${startIndex}-${endIndex}`);
} else if ('indexWithinParagraph' in args.target) {
// Find paragraph containing the specified index
log.info(
`Finding paragraph containing index ${args.target.indexWithinParagraph}${args.tabId ? ` in tab ${args.tabId}` : ''}`
);
const paragraphRange = await GDocsHelpers.getParagraphRange(
docs,
args.documentId,
args.target.indexWithinParagraph,
args.tabId
);
if (!paragraphRange) {
throw new UserError(
`Could not find paragraph containing index ${args.target.indexWithinParagraph}${args.tabId ? ` in tab ${args.tabId}` : ''}.`
);
}
startIndex = paragraphRange.startIndex;
endIndex = paragraphRange.endIndex;
log.info(`Located paragraph at range ${startIndex}-${endIndex}`);
} else if ('startIndex' in args.target && 'endIndex' in args.target) {
// Use directly provided range
startIndex = args.target.startIndex;
endIndex = args.target.endIndex;
log.info(`Using provided paragraph range ${startIndex}-${endIndex}`);
}
// Verify that we have a valid range
if (startIndex === undefined || endIndex === undefined) {
throw new UserError(
'Could not determine target paragraph range from the provided information.'
);
}
if (endIndex <= startIndex) {
throw new UserError(
`Invalid paragraph range: end index (${endIndex}) must be greater than start index (${startIndex}).`
);
}
// STEP 2: Build and apply the paragraph style request
log.info(`Building paragraph style request for range ${startIndex}-${endIndex}`);
const requestInfo = GDocsHelpers.buildUpdateParagraphStyleRequest(
startIndex,
endIndex,
args.style,
args.tabId
);
if (!requestInfo) {
return 'No valid paragraph styling options were provided.';
}
log.info(`Applying styles: ${requestInfo.fields.join(', ')}`);
await GDocsHelpers.executeBatchUpdate(docs, args.documentId, [requestInfo.request]);
return `Successfully applied paragraph styles (${requestInfo.fields.join(', ')}) to the paragraph${args.tabId ? ` in tab ${args.tabId}` : ''}.`;
} catch (error: any) {
// Detailed error logging
log.error(`Error applying paragraph style in doc ${args.documentId}:`);
log.error(error.stack || error.message || error);
if (error instanceof UserError) throw error;
if (error instanceof NotImplementedError) throw error;
// Provide a more helpful error message
throw new UserError(`Failed to apply paragraph style: ${error.message || 'Unknown error'}`);
}
},
});
}
|