Skip to content

feat(docs,sheets,slides): add docs.insertTable, sheets.getRanges, and slides.replaceImage#396

Open
matheusrmorgado wants to merge 2 commits into
gemini-cli-extensions:mainfrom
matheusrmorgado:feat/docs-insert-table-sheets-get-ranges-slides-replace-image
Open

feat(docs,sheets,slides): add docs.insertTable, sheets.getRanges, and slides.replaceImage#396
matheusrmorgado wants to merge 2 commits into
gemini-cli-extensions:mainfrom
matheusrmorgado:feat/docs-insert-table-sheets-get-ranges-slides-replace-image

Conversation

@matheusrmorgado

Copy link
Copy Markdown

Summary

Fixes #395 by adding one high-leverage tool to each of the Docs, Sheets, and Slides surfaces. All three follow the existing service-class, feature-group, and test patterns, and none of them adds a new OAuth scope (each tool reuses its feature group's existing scope, so the consent surface is unchanged).

docs.insertTable (docs.write group, default on)

Inserts a rows x columns table at the end of the body (default) or at a specific index, optionally pre-filled with cell data in the same call:

docs.insertTable({
  documentId: "...",
  rows: 3, columns: 2,
  data: [["Metric", "Value"], ["Revenue", "$1.2M"], ["Churn", "2.1%"]]
})

Cell fill works by re-reading the document to locate the inserted table, then applying one insertText per non-empty cell in reverse document order so earlier indexes remain valid. data dimensions are validated against rows/columns before any API call. This avoids the brittle alternative of asking the model to compute table-cell indexes by hand after insertion.

sheets.getRanges (sheets.read group, default on, readOnlyHint)

Batch read of multiple A1 ranges via spreadsheets.values.batchGet — one API call instead of N sheets.getRange calls when pulling disjoint ranges (e.g. KPI cells across sheets). Supports valueRenderOption (FORMATTED_VALUE default / UNFORMATTED_VALUE / FORMULA) and majorDimension (ROWS default / COLUMNS). Results are returned in request order.

slides.replaceImage (slides.write group, default off, like the other write tools)

Replaces an existing image by imageObjectId with a new URL via the replaceImage batchUpdate request, preserving the original position and size. imageReplaceMethod: CENTER_INSIDE (default) or CENTER_CROP. Pairs naturally with slides.getImages / slides.getMetadata and with slides.replaceAllText for template-deck workflows (refresh a chart, fill an image placeholder).

What's included

  • Service methods in DocsService, SheetsService, SlidesService following the existing logging/error-shape conventions (isError on failures)
  • Tool registration in index.ts with Zod schemas (integer/positive constraints, enums, min(1) on the ranges array) and readOnlyHint on the read tool
  • feature-config.ts entries in the matching feature groups
  • Jest coverage (12 new tests): request shapes, defaults, URL-to-ID extraction, reverse-order cell fill, dimension validation, empty-result and error paths
  • docs/index.md entries for the default-enabled tools (the Slides section lists only read tools today, so slides.replaceImage follows the existing convention of being config-documented only)
  • Skill recipes: google-docs (insertTable usage and why fill-at-insert beats post-hoc index math) and google-sheets (when to prefer getRanges over repeated getRange)

Verification

npm run test && npm run lint && npm run format:check && npx tsc --noEmit --project workspace-server

All passing locally: 29 suites, 632 tests (620 existing + 12 new), eslint and prettier clean, tsc clean.

Happy to split this into three per-product PRs if you prefer smaller reviews — the three changes are fully independent.

Made with Cursor

@google-cla

google-cla Bot commented Jun 12, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds three new tools to the Google Workspace extension: docs.insertTable for inserting pre-filled tables in Google Docs, sheets.getRanges for batch-retrieving multiple disjoint ranges in Google Sheets, and slides.replaceImage for replacing images in Google Slides. The feedback highlights a critical bug in DocsService.ts where using cellStart + 1 for cell text insertion will trigger a 400 Bad Request error on empty cells, requiring a shift to cellStart and a corresponding test update. Additionally, the error handler in SheetsService.ts for getRanges needs to include isError: true to ensure MCP clients can correctly identify tool execution failures.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread workspace-server/src/services/DocsService.ts Outdated
Comment thread workspace-server/src/__tests__/services/DocsService.test.ts
Comment thread workspace-server/src/services/SheetsService.ts
… slides.replaceImage

Three focused additions to the Docs/Sheets/Slides tool surfaces:

- docs.insertTable (docs.write): inserts a table at the end of the body or at
  a specific index, optionally pre-filled with cell data. Cell fill re-reads
  the document to locate the inserted table and applies insertText requests in
  reverse document order so earlier indexes stay valid. Validates that data
  fits within the declared dimensions before any API call.

- sheets.getRanges (sheets.read, readOnlyHint): batch read of multiple A1
  ranges via spreadsheets.values.batchGet, with valueRenderOption and
  majorDimension controls. One API call instead of N sheets.getRange calls
  when reading disjoint ranges.

- slides.replaceImage (slides.write): replaces an existing image by objectId
  with a new image URL via the replaceImage batchUpdate request, preserving
  position and size. CENTER_INSIDE (default) or CENTER_CROP fit. Pairs with
  slides.getImages / template workflows for refreshing charts and filling
  image placeholders.

Includes feature-config registration, Jest coverage for all three services
(request shapes, defaults, URL extraction, error paths, dimension
validation), docs/index.md entries for the default-enabled tools, and skill
recipes for google-docs and google-sheets.
…o getRanges failures

Addresses gemini-code-assist review: cellStart already points at the cell's
first paragraph, so inserting at cellStart + 1 landed on the terminating
newline and 400'd on empty cells; sheets.getRanges error responses now carry
isError: true so MCP clients can distinguish failures from content.
@matheusrmorgado matheusrmorgado force-pushed the feat/docs-insert-table-sheets-get-ranges-slides-replace-image branch from 1492733 to 8eedd9f Compare June 12, 2026 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: docs.insertTable, sheets.getRanges, and slides.replaceImage

1 participant