Skip to content

refactor: unified tool registry and agent executor#9

Merged
Ocean82 merged 2 commits into
mainfrom
pr/agent-tool-system
Jul 17, 2026
Merged

refactor: unified tool registry and agent executor#9
Ocean82 merged 2 commits into
mainfrom
pr/agent-tool-system

Conversation

@Ocean82

@Ocean82 Ocean82 commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Introduces a shared tool registry and refactors the agent executor layer.

Changes:

  • shared/toolRegistry with typed tool definitions and validation tests
  • shared/toolTypes for consistent tool type contracts
  • Refactored agent executor with format tests and parser improvements
  • New formatCellsTool, pendingActionPreview, previewBuilders modules
  • Removed legacy src/agent/types.ts (replaced by shared types)
  • Updated server prompt and parseResponse for new tool interface

Summary by Sourcery

Unify spreadsheet agent tools behind a shared, typed registry and update the agent execution, parsing, and server prompt/response layers to consume this single source of truth while improving formatting and filter behaviors.

New Features:

  • Introduce a canonical shared tool registry and shared tool type contracts used by both client and server.
  • Add a dedicated format_cells implementation that supports conditional value-based formatting, selection-aware ranges, and robust color handling.
  • Add preview builder utilities and helpers to surface structured cell change previews for applicable tool actions.

Bug Fixes:

  • Ensure template tools are executed via a dedicated template handler instead of falling through as unknown tools.
  • Fix formatting and coloring intents that were previously misrouted through find-and-replace by routing them through the new format_cells tool.
  • Improve safety of numeric operations such as modify_column by validating numeric factors and handling missing formula targets in apply_formula.
  • Align filter behavior to support header names or column letters and normalize condition/value mapping for the underlying filter configuration.

Enhancements:

  • Refine the agent parser and act templates to recognize richer formatting and highlighting intents and emit consistent format_cells actions.
  • Extend the agent executor contract to support filters, charts, templates, and selection-aware formatting while using shared tool name resolution.
  • Add shared helpers for formatting cell values and conditional rule types, including support for data bar formatting.
  • Introduce utilities to find active pending action previews for the chat UI and to normalize scalar cell values for analysis.

Documentation:

  • Update the server action prompt text to derive tool documentation from the shared registry and clarify how format_cells conditional formatting should be used.

Tests:

  • Add comprehensive tests for the new format_cells tool behavior and its interaction with the executor and parser.
  • Add shared tests to validate the tool registry schema, alias resolution, and alignment with the server allowlist and prompts.
  • Add parser tests covering new formatting intents and regression cases around find-and-replace vs. formatting.
  • Add tests for preview builder utilities and pending action preview selection to ensure correct UI previews of tool effects.

- Add shared/toolRegistry with typed tool definitions and validation
- Add shared/toolTypes for consistent tool type contracts
- Refactor agent executor with format tests and parser improvements
- Add formatCellsTool, pendingActionPreview, previewBuilders
- Remove legacy src/agent/types.ts (replaced by shared types)
- Update server prompt and parseResponse for new tool interface
@sourcery-ai

sourcery-ai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refactors the spreadsheet agent to use a shared, typed tool registry and central format_cells implementation, updates the executor/parser/server prompt to this new contract, and adds tests plus preview helpers for formatting and action previews.

Sequence diagram for message parsing and unified format_cells execution

sequenceDiagram
  actor User
  participant AgentIndex as agent.index
  participant Parser as parser.parseMessage
  participant Executor as executor.executeTool
  participant FormatCells as formatCellsTool.applyFormatCells
  participant ToolRegistry as shared.toolRegistry

  User->>AgentIndex: send message
  AgentIndex->>Parser: parseMessage(message, sheetContext)
  Parser-->>AgentIndex: ParseResult(calls)
  AgentIndex->>Executor: executeTool(call, ctx)
  Executor->>ToolRegistry: resolveToolName(call.tool)
  ToolRegistry-->>Executor: canonicalToolName (e.g. format_cells)
  Executor->>FormatCells: applyFormatCells(params, ctx)
  FormatCells-->>Executor: ExecutionResult
  Executor-->>AgentIndex: ExecutionResult
  AgentIndex-->>User: updated sheet & explanation
Loading

File-Level Changes

Change Details Files
Agent tools now re-export a canonical shared tool registry and shared type contracts used by both client and server.
  • Replaced inlined TOOL_REGISTRY and helper functions with re-exports from the shared registry module
  • Introduced shared toolTypes definitions (ToolDefinition, FormatCellsParams, FormatCondition, categories, aliases, hidden tools)
  • Updated agent index barrel exports to surface the new registry and type contracts
src/agent/tools.ts
src/agent/index.ts
shared/toolTypes.ts
shared/toolRegistry.ts
Executor is wired to the shared registry, adds format_cells, filter, and template delegation, and removes legacy formatting helpers.
  • Resolved tool names via resolveToolName and added alias parameter normalization (e.g., conditional_format → format_cells)
  • Replaced format_range/conditional_format execution with a centralized applyFormatCells implementation
  • Added filter tool implementation mapping column letters or header names to FilterConfig with condition/value mapping
  • Delegated template tools (create_*) to an optional executeTemplate context hook and added optional chart support
  • Introduced helper functions for column resolution and removed the old expandRange helper
src/agent/executor.ts
src/lib/formatCellsTool.ts
src/lib/formatCellsTool.test.ts
Parser and act templates recognize richer formatting/color intents and route them to format_cells instead of find_and_replace.
  • Added color-word dictionaries and regexes to detect font color and highlight intents
  • Parsed phrases like 'change the text to red' and 'highlight cells containing 4' into format_cells calls with appropriate params
  • Ensured conditional negative highlighting still works while avoiding misclassification of genuine find/replace requests
  • Extended SheetContext and added parser tests to cover new formatting behaviors and regression cases
src/agent/parser.ts
src/agent/parser.test.ts
shared/actTemplates.ts
Server prompt and response parsing now derive allowed tools and tool docs from the shared registry, with read-only tools excluded from actions.
  • Replaced hard-coded SPREADSHEET_AGENT_TOOLS and ALLOWED_TOOLS with ACTION_TOOL_NAMES from the shared registry
  • Switched the action prompt tool listing to use formatToolsForPrompt plus explicit format_cells condition examples
  • Documented that analytical questions should be answered in prose without emitting actions
  • Added registry tests to validate alias wiring, action/mutation/template tool sets, and server allowlist behavior
server/src/prompt.ts
server/src/parseResponse.ts
shared/toolRegistry.test.ts
Introduced preview builder utilities and pending-action preview selection to power grid overlay previews.
  • Added preview builders for set_range and modify_column that compute CellChange previews
  • Added a helper to attach preview changes to actions where applicable
  • Introduced a utility to locate the latest pending action with preview changes and map them by cell id
  • Added tests to cover preview computation and selection behavior
src/lib/previewBuilders.ts
src/lib/previewBuilders.test.ts
src/lib/pendingActionPreview.ts
src/lib/pendingActionPreview.test.ts
Miscellaneous type and utility enhancements to support analysis and new formatting modes.
  • Added cellScalar utility for coercing raw cell values into analysis-friendly scalars
  • Extended ConditionalRule with a dataBar type and optional dataBarColor for future conditional formats
  • Added an executor-format integration test suite for formatting, filters, and template delegation
  • Documented an unused llmIntentParser module with a TODO comment for future integration or removal
src/lib/formatUtils.ts
src/types/index.ts
src/agent/executor.format.test.ts
server/src/llmIntentParser.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@Ocean82, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 25 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cfc83fb1-c763-467e-87fa-f25fae76a982

📥 Commits

Reviewing files that changed from the base of the PR and between 395ca32 and 1868a88.

📒 Files selected for processing (23)
  • server/src/llmIntentParser.ts
  • server/src/parseResponse.ts
  • server/src/prompt.ts
  • shared/actTemplates.ts
  • shared/colorMaps.ts
  • shared/toolRegistry.test.ts
  • shared/toolRegistry.ts
  • shared/toolTypes.ts
  • src/agent/executor.format.test.ts
  • src/agent/executor.ts
  • src/agent/index.ts
  • src/agent/parser.test.ts
  • src/agent/parser.ts
  • src/agent/tools.ts
  • src/agent/types.ts
  • src/lib/formatCellsTool.test.ts
  • src/lib/formatCellsTool.ts
  • src/lib/formatUtils.ts
  • src/lib/pendingActionPreview.test.ts
  • src/lib/pendingActionPreview.ts
  • src/lib/previewBuilders.test.ts
  • src/lib/previewBuilders.ts
  • src/types/index.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • The FONT_COLOR_HEX and HIGHLIGHT_BG_HEX maps are now duplicated in both src/agent/parser.ts and shared/actTemplates.ts; consider centralizing these in a shared helper to avoid drift between the fast-path parser and the LLM templates.
  • resolveColumnIndex currently scans a fixed 60 columns and relies on findHeaderRow; it might be more robust to derive the column limit from the actual sheet shape (e.g., lastDataCol or header row cells) instead of a magic constant.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The FONT_COLOR_HEX and HIGHLIGHT_BG_HEX maps are now duplicated in both src/agent/parser.ts and shared/actTemplates.ts; consider centralizing these in a shared helper to avoid drift between the fast-path parser and the LLM templates.
- resolveColumnIndex currently scans a fixed 60 columns and relies on findHeaderRow; it might be more robust to derive the column limit from the actual sheet shape (e.g., lastDataCol or header row cells) instead of a magic constant.

## Individual Comments

### Comment 1
<location path="src/agent/executor.ts" line_range="315-323" />
<code_context>
+}
+
+/** Resolve a column given as a letter ("B") or a header name ("Amount"). */
+function resolveColumnIndex(
+  column: string,
+  sheet: SheetData,
+  getComputedValue: (row: number, col: number) => string,
+): number | null {
+  if (/^[A-Z]{1,3}$/i.test(column)) return letterToCol(column.toUpperCase())
+  const headerRow = findHeaderRow(sheet)
+  const lowered = column.toLowerCase()
+  for (let c = 0; c < 60; c++) {
+    if (getComputedValue(headerRow, c).toLowerCase() === lowered) return c
+  }
</code_context>
<issue_to_address>
**issue:** resolveColumnIndex doesn’t guard against missing header rows and uses a hard-coded column scan limit.

If `findHeaderRow(sheet)` returns `-1`, `getComputedValue(headerRow, c)` will be called with a negative row index, which can misbehave. Also, scanning with `for (let c = 0; c < 60; c++)` assumes a 60-column sheet and will miss headers on wider sheets. Please short-circuit when `headerRow < 0`, and use the sheet’s actual last data column or metadata instead of the hard-coded limit.
</issue_to_address>

Fix all in Cursor


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/agent/executor.ts Outdated
Comment on lines +315 to +323
function resolveColumnIndex(
column: string,
sheet: SheetData,
getComputedValue: (row: number, col: number) => string,
): number | null {
if (/^[A-Z]{1,3}$/i.test(column)) return letterToCol(column.toUpperCase())
const headerRow = findHeaderRow(sheet)
const lowered = column.toLowerCase()
for (let c = 0; c < 60; c++) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue: resolveColumnIndex doesn’t guard against missing header rows and uses a hard-coded column scan limit.

If findHeaderRow(sheet) returns -1, getComputedValue(headerRow, c) will be called with a negative row index, which can misbehave. Also, scanning with for (let c = 0; c < 60; c++) assumes a 60-column sheet and will miss headers on wider sheets. Please short-circuit when headerRow < 0, and use the sheet’s actual last data column or metadata instead of the hard-coded limit.

Fix in Cursor

…mnIndex

- Extract FONT_COLOR_HEX and HIGHLIGHT_BG_HEX into shared/colorMaps.ts
  to avoid drift between parser and actTemplates
- resolveColumnIndex now derives max column from actual sheet data
  instead of hardcoded 60-column limit
@Ocean82
Ocean82 merged commit 4ee9d11 into main Jul 17, 2026
2 of 3 checks passed
@Ocean82
Ocean82 deleted the pr/agent-tool-system branch July 19, 2026 11:40
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.

1 participant