Skip to content

feat: add cursor native tools#1

Merged
kenryu42 merged 25 commits into
mainfrom
cursor-native-tools
Jun 2, 2026
Merged

feat: add cursor native tools#1
kenryu42 merged 25 commits into
mainfrom
cursor-native-tools

Conversation

@kenryu42
Copy link
Copy Markdown
Owner

@kenryu42 kenryu42 commented Jun 2, 2026

Summary by CodeRabbit

  • New Features

    • OAuth authentication for Grok CLI access
    • File management tools: list, read, write, edit, delete
    • Search tools: grep and glob pattern matching
    • Shell command execution
    • Quota and rate-limit monitoring with local caching
  • Documentation

    • README updated with Grok CLI integration, cursor-tool compatibility, and env var guidance
  • Tests

    • Expanded test coverage for provider, tools, auth, and payload handling

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

Warning

Review limit reached

@kenryu42, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 25 minutes. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

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.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1ee7f8b9-55b3-4503-a154-624d6f7e1182

📥 Commits

Reviewing files that changed from the base of the PR and between eb0bea0 and 381868e.

📒 Files selected for processing (3)
  • src/tools/rendering.ts
  • src/tools/search.ts
  • tests/tools/search.test.ts
📝 Walkthrough

Walkthrough

This PR refactors the Grok CLI extension from a monolithic implementation into a modular architecture. It introduces OAuth 2.0+PKCE authentication, splits payload sanitization and tools into dedicated modules, centralizes provider registration with quota caching and model resolution, and adds comprehensive Cursor-style tool shims for file operations, searching, and shell execution.

Changes

OAuth, Error Types, and Model Catalog Foundation

Layer / File(s) Summary
xAI OAuth 2.0 and PKCE Implementation
src/auth/oauth.ts, tests/auth/oauth.test.ts
Implements complete OAuth authorization-code flow with PKCE, OIDC discovery, loopback callback server, token exchange, and refresh logic; extensive tests validate discovery, login, token refresh with HTTP-based failure classification, and error handling.
OAuth Error Types and Codes
src/shared/errors.ts, tests/shared/errors.test.ts
Defines XaiOAuthError exception class and XaiErrorCode constant mapping OAuth/login failure scenarios for consistent error classification and relogin requirement flagging.
Model Catalog and Reasoning Effort Support
src/models/catalog.ts, tests/models/catalog.test.ts
Refactored model catalog moved from root src/models.ts defining per-model capabilities, cost/context windows, and environment-based model resolution with fallback defaults.

Payload Sanitization and Tool Infrastructure

Layer / File(s) Summary
Payload Sanitization for xAI Responses API
src/payload/sanitize.ts, tests/payload/sanitize.test.ts
Normalizes provider request payloads for xAI API quirks: filters inputs, lifts instructions, converts local image paths to data URIs, rewrites function-call-output, maps response formats, manages reasoning effort by model, and caches session IDs.
Tool Rendering and Execution Helpers
src/tools/rendering.ts, tests/tools/rendering.test.ts
Shared utilities for tool output rendering, typed detail extraction, ripgrep/grep command execution with fallback, output truncation to 50KB, and standardized error/result construction patterns.
File System Tools (LS, Read, Write, StrReplace, Edit, Delete)
src/tools/files.ts, tests/tools/files.test.ts
Registers six file-manipulation tools with consistent error handling, UTF-8 byte reporting, multi-variant argument normalization supporting both Grok and Cursor styles.
Search Tools (Grep, Glob)
src/tools/search.ts, tests/tools/search.test.ts
Registers ripgrep-based Grep and Glob tools with fallback to grep/find, regex patterns, file globbing with mtime sorting, include filters, and graceful rg unavailability handling.
Shell Tool Registration
src/tools/shell.ts, tests/tools/shell.test.ts
Registers Shell tool executing bash commands with configurable timeout and working directory, captures exit codes and output, renders command execution state.
Tool Registration Orchestrator
src/tools/register.ts, tests/tools/register.test.ts
Exports registerGrokTools wiring all tool families (search, file, shell) into the extension via a single function; test verifies expected tool names and render functions.
Tool Test Helpers
tests/tools/toolTestHelpers.ts
Test utilities for registering and executing tools against mock ExtensionAPI, including tool result rendering, text extraction, and temporary directory lifecycle management.

Provider Registration and Integration

Layer / File(s) Summary
Quota Caching and Rate Limit Management
src/provider/quota.ts
Manages local quota cache storage, extracts rate-limit metadata from response headers, formats human-readable quota reports with request/token counts and zero-retention status.
Streaming Integration with Rate Limit Capture
src/provider/stream.ts
Wraps OpenAI-compatible streaming to inject Grok CLI headers, captures rate-limit headers from responses, forwards callbacks.
Tool Scope Synchronization
src/provider/toolScope.ts
Syncs active editor tools based on provider selection: removes/re-adds Grok tool shims when switching providers, avoiding redundant updates.
Grok CLI Status Command
src/provider/status.ts
Registers grok-cli-status command reporting env-token bypass state, registered model count, and cached quota metrics with OAuth error formatting.
Grok CLI Provider Registration
src/provider/register.ts, tests/provider/register.test.ts
Central orchestrator wiring OAuth login/refresh, quota caching, model resolution, tool synchronization, before-request sanitization, status command, and conditional token-bypass warnings; extensive tests validate status output, quota persistence, provider metadata, sanitization, and tool scoping.

Configuration and Documentation Updates

Layer / File(s) Summary
Code Style and Build Configuration
biome.json, tsconfig.json, vitest.config.ts, .release-tools/config.ts, .release-tools/cache.json
Updates formatter settings to use spaces/indent-width 2, single quotes, trailing commas, explicit line width/semicolon rules; reformats config files to match new style.
Package Manifest and README Updates
package.json, README.md
Adds @earendil-works/pi-tui to peerDependencies and devDependencies; clarifies Grok CLI model availability, documents Cursor tool compatibility with argument normalization, includes GROK_CLI_OAUTH_TOKEN environment variable.
Ignore Files and Minor Config
.gitignore, .ignore, knip.json
Adds docs/ to ignore lists and reformats JSON indentation.
Extension Entrypoint Refactoring
src/index.ts
Simplifies to re-export from ./provider/register.js, removing 341 lines of monolithic provider setup.
Deletions of Monolithic Modules
src/oauth.ts, src/models.ts, src/sanitize.ts, src/errors.ts, tests/oauth.test.ts, tests/models.test.ts, tests/sanitize.test.ts, tests/errors.test.ts, tests/index.test.ts, tests/package.test.ts
Removes monolithic implementations as functionality is split into modular subdirectories (src/auth/, src/models/, src/payload/, src/shared/, src/provider/).
Package and Repository Contract Tests
tests/provider/package.test.ts
Tests validating package manifest, npm scripts, devDependencies, and repository layout including assertions that old files no longer exist.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 A modular home we've built today,
With OAuth locks and tools at play,
From monolith to clean design,
Each provider shines and tests align!
Grok CLI's journey, spread with care,
A refactored future, beyond compare! 🌟

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor-native-tools

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

🧹 Nitpick comments (2)
README.md (1)

76-76: 💤 Low value

Consider expanding the token bypass documentation.

The description "(no auto-refresh)" is accurate but users may not understand the implications. Consider noting that this bypasses the OAuth flow entirely and requires manual token management when it expires.

📝 Suggested documentation enhancement
-| `GROK_CLI_OAUTH_TOKEN` | — | Direct token bypass (no auto-refresh) |
+| `GROK_CLI_OAUTH_TOKEN` | — | Direct token bypass (skips OAuth flow; no auto-refresh; requires manual token management) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 76, Update the README entry for the environment variable
GROK_CLI_OAUTH_TOKEN to clarify that it bypasses the OAuth flow entirely and
that tokens must be managed manually: expand the description to state that
supplying GROK_CLI_OAUTH_TOKEN prevents automatic refresh/renewal, requires
users to provide a valid access token obtained externally, and they must replace
or rotate the token when it expires to restore CLI functionality.
src/provider/toolScope.ts (1)

3-13: ⚡ Quick win

Keep the Grok tool list in one production source.

Lines 3-13 need to stay in lockstep with the names registered elsewhere. Make this the canonical export consumed by registration/scoping code, or import the registration list here, so adding or renaming a tool can't leave scope management out of sync.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/provider/toolScope.ts` around lines 3 - 13, GROK_TOOL_NAMES is currently
a standalone array that can drift from registered tool names; make this the
single source of truth by either exporting the registration list from the module
that registers tools and replacing this array with an import of that exported
list, or move/export GROK_TOOL_NAMES from this file into the
registration/scoping module and update all consumers to import it; locate usages
referencing GROK_TOOL_NAMES and the registration logic (the tool registration
function or module) and update imports so only one exported symbol controls tool
names to keep registration and scoping in sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/auth/oauth.ts`:
- Around line 131-136: The JSON parsing of the discovery response (the await
response.json() assigned to payload) can throw a SyntaxError for HTML/proxy
bodies and must be wrapped — catch errors from response.json() and rethrow them
as XaiOAuthError with the DISCOVERY_FAILED classification so callers retain the
discovery-failure semantics; update the block around payload = (await
response.json())... to try/catch, on failure throw new
XaiOAuthError('DISCOVERY_FAILED', '...') including the original error
message/details, and keep using
validateEndpoint(String(payload.authorization_endpoint ?? ''),
'authorization_endpoint') and validateEndpoint(String(payload.token_endpoint ??
''), 'token_endpoint') as before.
- Around line 217-240: The current oauth callback server flow never surfaces the
dedicated error codes CALLBACK_BIND_FAILED and CALLBACK_TIMEOUT; modify the
listen()/server startup and the waitForCallback implementation so that if both
listen(CALLBACK_PORT) and listen(0) fail you return/resolve using the
CALLBACK_BIND_FAILED result (instead of letting the raw error leak) and change
the timeout branch in waitForCallback to resolve with CALLBACK_TIMEOUT (instead
of the generic 'timeout'/'AUTHORIZATION_FAILED' mapping upstream). Update the
logic around the listen calls and the Promise.race in the waitForCallback
returned object (referencing listen, CALLBACK_PORT, CALLBACK_HOST,
CALLBACK_PATH, server, callbackPromise, waitForCallback, CALLBACK_BIND_FAILED,
CALLBACK_TIMEOUT) to produce those specific CallbackResult error codes so
upstream can distinguish bind failures from timeouts.
- Around line 252-272: The token POSTs (token exchange and refresh) lack
timeouts and don't convert transport/JSON errors to XaiOAuthError; wrap both
fetch calls (the one using tokenEndpoint with body including
grant_type/authorization_code and the refresh flow around lines 384-406) in
try/catch, use an AbortController with a short configurable timeout to abort
stalled requests, and on any fetch/network/response.json() error throw
XaiOAuthError with the appropriate XaiErrorCode (use
XaiErrorCode.TOKEN_EXCHANGE_FAILED for the authorization_code exchange and
XaiErrorCode.REFRESH_FAILED for refresh), preserving useful context
(status/text/inner error) in the error message; also ensure non-OK responses are
still handled as before but include the aborted/parse errors in the same
XaiOAuthError shape.

In `@src/models/catalog.ts`:
- Around line 45-52: The composer entries declare thinkingLevelMap values that
indicate no supported reasoning levels, but supportsReasoningEffort() currently
returns true for all grok-composer* ids causing sanitizePayload() to retain
reasoning.effort; update supportsReasoningEffort() to look up the model entry
(from the same catalog where thinkingLevelMap is defined) and return true only
if the model's reasoning flag is true AND the thinkingLevelMap contains at least
one valid level (i.e., a value that is neither null nor the sentinel 'none');
use the catalog entry key and the thinkingLevelMap symbol to implement this
check so sanitizePayload() will correctly strip reasoning.effort for
grok-composer models.

In `@src/payload/sanitize.ts`:
- Around line 278-282: The current code only deletes next.response_format when
it creates next.text, leaving response_format present if next.text already
exists; update the logic in sanitize.ts so that if next.response_format is
present you set next.text = { format: next.response_format } only when next.text
is absent (preserving existing next.text) but in all cases remove
next.response_format afterward—i.e., always delete next.response_format after
handling it while avoiding overwriting an existing next.text.
- Around line 248-265: The current loop only extracts leading
'system'/'developer' messages into instructionParts but leaves any such messages
later in input; instead iterate over the entire input array, collect and remove
every element whose role is 'system' or 'developer' (use textFromContent((item
as Record<string, unknown>).content).trim() to extract text) into
instructionParts, then merge into next.instructions as before (respecting
existing value and joining with '\n\n'); update the input array in-place or
replace it with the filtered array so no 'system'/'developer' entries remain
before sending to xAI.

In `@src/tools/files.ts`:
- Line 141: The code currently computes targetPath via resolve(ctx.cwd,
params.path) (see targetPath, ctx.cwd, params.path, resolve) but accepts
absolute/../ inputs and can escape the workspace; add a single guard function
(e.g., ensurePathInWorkspace or canonicalizeWithinWorkspace) that: 1) joins and
resolves the candidate path, 2) calls fs.realpath on the candidate and on
ctx.cwd to canonicalize symlinks, 3) verifies the real candidate path starts
with the real workspace root (reject otherwise), and 4) returns the
canonicalized path; replace the direct resolve(...) usage in all file-tool
locations that set targetPath (the occurrences around
targetPath/ctx.cwd/params.path and the other listed sites) to call this guard
and throw a clear error when outside the workspace.

In `@src/tools/rendering.ts`:
- Around line 125-160: fileError and toolError currently discard failure state
in the returned details, causing collapsed renderers to treat errors as
empty-success results; update both functions (fileError and toolError) to
include an explicit error indicator in the details object (e.g., add an "error"
string/message or a boolean "failed" flag) so ToolResult<T>.details carries the
failure info (ensure the generic T is extended/augmented or the functions cast
to include the new field) and update the Grep special-case to still set that
error indicator when returning "No matches found" only for genuine no-match vs.
actual failures.

In `@src/tools/search.ts`:
- Around line 192-202: The fallback using execFileAsync + find builds matcher
from globToRegExp(normalizePath(params.pattern)) but always tests against
normalizePath(relative(ctx.cwd, file)), which makes basename-only patterns like
"*.ts" fail for nested files; update the filter in the search fallback so that
if params.pattern contains a path separator (i.e., includes '/' after
normalization) you test matcher.test(normalizePath(relative(ctx.cwd, file))) but
if it is a basename-only pattern you test matcher.test(path.basename(file)) (use
path.basename or equivalent), keeping use of matcher, globToRegExp,
normalizePath, params.pattern and execFileAsync/find logic intact.

In `@src/tools/shell.ts`:
- Around line 47-52: The shell runner currently hardcodes execFileAsync('bash',
['-c', params.command], ...) which will fail on systems without bash; update the
code in the function that invokes execFileAsync to detect the platform and
available shells (use process.platform to choose 'bash' on POSIX where present,
fallback to 'sh' for generic POSIX, and use 'cmd.exe' / 'powershell.exe' on
Windows as appropriate), or attempt to stat/which the chosen shell and if not
found return a clear, typed error like "unsupported platform or shell not found"
instead of calling execFileAsync; reference the execFileAsync call,
params.command, MAX_OUTPUT_BYTES, timeout, and signal when implementing the
platform-aware runner and error path.

In `@tests/tools/search.test.ts`:
- Around line 151-155: The test mutates process.env.PATH and calls
vi.resetModules() before performing the dynamic import and collectTools call,
which can leak a modified PATH if the import fails; wrap the dynamic import of
'../../src/tools/search.js' (and the call to collectTools and vi.resetModules())
inside a try block and restore the original PATH in a finally block so
process.env.PATH is always reset, i.e., save const oldPath = process.env.PATH
before changing it, move process.env.PATH = bin and vi.resetModules() into the
try, perform the import and collectTools(registerSearchTools) there, and in
finally set process.env.PATH = oldPath to guarantee restoration even on error.

---

Nitpick comments:
In `@README.md`:
- Line 76: Update the README entry for the environment variable
GROK_CLI_OAUTH_TOKEN to clarify that it bypasses the OAuth flow entirely and
that tokens must be managed manually: expand the description to state that
supplying GROK_CLI_OAUTH_TOKEN prevents automatic refresh/renewal, requires
users to provide a valid access token obtained externally, and they must replace
or rotate the token when it expires to restore CLI functionality.

In `@src/provider/toolScope.ts`:
- Around line 3-13: GROK_TOOL_NAMES is currently a standalone array that can
drift from registered tool names; make this the single source of truth by either
exporting the registration list from the module that registers tools and
replacing this array with an import of that exported list, or move/export
GROK_TOOL_NAMES from this file into the registration/scoping module and update
all consumers to import it; locate usages referencing GROK_TOOL_NAMES and the
registration logic (the tool registration function or module) and update imports
so only one exported symbol controls tool names to keep registration and scoping
in sync.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0723d8fe-2c5b-4b30-b124-7b80d5c19c0f

📥 Commits

Reviewing files that changed from the base of the PR and between 6b1b059 and 6f89545.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (47)
  • .gitignore
  • .ignore
  • .release-tools/cache.json
  • .release-tools/config.ts
  • README.md
  • biome.json
  • knip.json
  • package.json
  • src/auth/oauth.ts
  • src/errors.ts
  • src/index.ts
  • src/models.ts
  • src/models/catalog.ts
  • src/oauth.ts
  • src/payload/sanitize.ts
  • src/provider/quota.ts
  • src/provider/register.ts
  • src/provider/status.ts
  • src/provider/stream.ts
  • src/provider/toolScope.ts
  • src/sanitize.ts
  • src/shared/errors.ts
  • src/tools/files.ts
  • src/tools/register.ts
  • src/tools/rendering.ts
  • src/tools/search.ts
  • src/tools/shell.ts
  • tests/auth/oauth.test.ts
  • tests/errors.test.ts
  • tests/index.test.ts
  • tests/models.test.ts
  • tests/models/catalog.test.ts
  • tests/oauth.test.ts
  • tests/package.test.ts
  • tests/payload/sanitize.test.ts
  • tests/provider/package.test.ts
  • tests/provider/register.test.ts
  • tests/sanitize.test.ts
  • tests/shared/errors.test.ts
  • tests/tools/files.test.ts
  • tests/tools/register.test.ts
  • tests/tools/rendering.test.ts
  • tests/tools/search.test.ts
  • tests/tools/shell.test.ts
  • tests/tools/toolTestHelpers.ts
  • tsconfig.json
  • vitest.config.ts
💤 Files with no reviewable changes (10)
  • tests/index.test.ts
  • tests/package.test.ts
  • src/errors.ts
  • src/sanitize.ts
  • tests/sanitize.test.ts
  • tests/errors.test.ts
  • tests/models.test.ts
  • src/oauth.ts
  • src/models.ts
  • tests/oauth.test.ts

Comment thread src/auth/oauth.ts Outdated
Comment thread src/auth/oauth.ts
Comment thread src/auth/oauth.ts Outdated
Comment thread src/models/catalog.ts
Comment thread src/payload/sanitize.ts
Comment thread src/tools/files.ts
Comment thread src/tools/rendering.ts
Comment thread src/tools/search.ts Outdated
Comment thread src/tools/shell.ts Outdated
Comment thread tests/tools/search.test.ts Outdated
@kenryu42
Copy link
Copy Markdown
Owner Author

kenryu42 commented Jun 2, 2026

@greptileai review

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Jun 2, 2026

Greptile Summary

This PR adds Cursor-native tool shims (file, search, shell tools) for Grok CLI models running inside the pi extension host, along with OAuth authentication, rate-limit quota caching, and payload sanitization for xAI's Responses API quirks. Several previously-reported issues (Glob's find fallback, LS's Unix ls, image path traversal, hard-coded quota model IDs) have been fixed.

  • New tools: Read, Write, StrReplace, Edit, Delete, LS, Grep, Glob, and Shell shimmed to translate Cursor/Grok argument shapes into pi tool calls, with workspace-boundary enforcement via canonicalizeWithinWorkspace.
  • Infrastructure: Quota/rate-limit headers are captured per-model and persisted to ~/.pi/grok-cli-quota.json; a /grok-cli-status command surfaces cached quota data for all registered models.
  • Auth: Full OAuth 2.0 + PKCE loopback flow with OIDC discovery, endpoint origin validation, state/CSRF check, and automatic token refresh.

Confidence Score: 4/5

Safe to merge for macOS/Linux users; Windows users will find the Grep tool non-functional without ripgrep installed.

The core tool shims, OAuth flow, workspace boundary enforcement, and payload sanitization are all well-constructed. One functional gap remains: execWithRgFallback in rendering.ts falls back to the system grep binary, which is absent on Windows — leaving the Grep tool completely broken on that platform when ripgrep is not installed. The Glob tool's identical problem was fixed in this PR (using a portable listFilesRecursive walk), making the Grep omission stand out. Everything else — auth, quota caching, file tools, sanitization — looks correct and production-ready.

src/tools/rendering.ts — the execWithRgFallback function needs a portable fallback path analogous to what was done for the Glob tool.

Important Files Changed

Filename Overview
src/tools/rendering.ts New shared utility module; Grep's grep fallback is not portable to Windows — inconsistent with the now-fixed Glob fallback.
src/tools/search.ts Glob fallback switched from Unix find to a portable Node.js recursive walk; sortByModifiedNewest uses synchronous statSync inside the sort comparator which can throw on TOCTOU deletion.
src/tools/files.ts LS tool replaced Unix ls with portable fs.readdir; all file paths routed through canonicalizeWithinWorkspace — workspace boundary enforcement looks correct.
src/tools/shell.ts Shell tool has proper platform detection for Windows/macOS/Linux; working_directory is not workspace-bounded by design since the tool already executes arbitrary commands.
src/payload/sanitize.ts Image path traversal issue fixed — resolveLocalImagePath now accepts cwd and calls ensurePathWithinWorkspace; function_call_output image rewriting logic looks correct.
src/auth/oauth.ts Full OAuth 2.0 + PKCE flow with OIDC discovery, HTTPS enforcement, origin allowlist, state/CSRF check, and loopback callback server — implementation looks solid.
src/provider/register.ts Provider registration wires together OAuth, tool sync, payload sanitization, and status command correctly; cwd is now properly threaded into sanitizePayload.

Sequence Diagram

sequenceDiagram
  participant LLM
  participant pi as pi Extension Host
  participant GrokTool as Grok Tool Shim
  participant FS as Filesystem
  participant API as cli-chat-proxy.grok.com

  LLM->>pi: Tool call (e.g. Read, Write, Grep, Shell)
  pi->>GrokTool: prepareArguments (normalize Cursor arg shapes)
  GrokTool->>GrokTool: canonicalizeWithinWorkspace (enforce workspace boundary)
  GrokTool->>FS: File / search / shell operation
  FS-->>GrokTool: result
  GrokTool-->>pi: ToolResult (content + details)
  pi-->>LLM: tool_result

  LLM->>pi: Next message (may include images)
  pi->>pi: "before_provider_request -> sanitizePayload"
  pi->>pi: Normalize image_url to input_image + base64
  pi->>pi: Strip reasoning items, move system to instructions
  pi->>API: "POST /v1/responses (with x-grok-* headers)"
  API-->>pi: SSE stream + rate-limit headers
  pi->>pi: "captureRateLimit -> persist quota cache"
  pi-->>LLM: assistant message
Loading

Fix All in Codex

Reviews (2): Last reviewed commit: "fix: make tool fallbacks and image paths..." | Re-trigger Greptile

Comment thread src/tools/files.ts Outdated
Comment thread src/tools/search.ts Outdated
Comment thread src/payload/sanitize.ts Outdated
Comment thread src/provider/status.ts Outdated
Comment thread src/provider/stream.ts
@kenryu42
Copy link
Copy Markdown
Owner Author

kenryu42 commented Jun 2, 2026

@greptileai review

Comment thread src/tools/rendering.ts
Comment on lines +164 to +183
export async function execWithRgFallback(
rgArgs: string[],
grepArgs: string[],
options: { cwd: string; signal?: AbortSignal },
): Promise<string> {
if (await hasRipgrep()) {
const result = await execFileAsync('rg', rgArgs, {
cwd: options.cwd,
maxBuffer: MAX_OUTPUT_BYTES,
signal: options.signal,
});
return result.stdout;
}
const result = await execFileAsync('grep', grepArgs, {
cwd: options.cwd,
maxBuffer: MAX_OUTPUT_BYTES,
signal: options.signal,
});
return result.stdout;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Grep fallback uses system grep, broken on Windows without ripgrep

execWithRgFallback falls back to execFileAsync('grep', ...) when ripgrep is unavailable. grep is not a native Windows binary, so on Windows without ripgrep installed the Grep tool will always fail at runtime. This is the same class of problem the Glob fallback already fixed in this PR (switching from Unix find to a portable listFilesRecursive Node.js walk). The Grep fallback needs a similarly portable alternative — for example, using listFilesRecursive to enumerate candidate files and then applying a JS regex over their contents.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex

@kenryu42 kenryu42 merged commit fd11cf7 into main Jun 2, 2026
3 checks passed
@kenryu42 kenryu42 deleted the cursor-native-tools branch June 2, 2026 19:09
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