Skip to content

fix(eve): return tool errors as execute results - #108

Merged
HugoRCD merged 2 commits into
mainfrom
fix/eve-tool-error-result
Aug 26, 2026
Merged

fix(eve): return tool errors as execute results#108
HugoRCD merged 2 commits into
mainfrom
fix/eve-tool-error-result

Conversation

@HugoRCD

@HugoRCD HugoRCD commented Aug 26, 2026

Copy link
Copy Markdown
Member

Summary

  • Eve GitHub execute now returns { error } on failure instead of throwing.
  • Eve's tool-loop logs thrown execute errors (tool execution failed) but does not always append a tool_result, so the next model call dies with MODEL_CALL_FAILED (tool_use without tool_result).
  • Token mint failures, GitHub 403/429, and other core throws stay visible to the model as a normal tool result.

Stacked on the Connect OIDC PR (this branch → fix/connect-oidc-env-tokenevl-343main).

Approval deny and the stale World Event id is not slot-numbered spam are still eve/world-local — not fixable in this repo.

Test plan

  • pnpm --filter @github-tools/sdk test
  • Force a token failure in examples/eve and confirm the turn continues with { error } instead of MODEL_CALL_FAILED
  • Confirm a successful tool still returns its normal payload
@vercel

vercel Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
github-tools-docs Ready Ready Preview, v0 Aug 26, 2026 9:43am
github-tools-test-agent Ready Ready Preview, v0 Aug 26, 2026 9:43am
@github-actions

Copy link
Copy Markdown
Contributor

Thank you for following the naming conventions! 🙏

Comment thread packages/github-tools/src/eve/steps.ts
Base automatically changed from fix/connect-oidc-env-token to main August 26, 2026 09:41
Eve's tool-loop logs thrown execute errors without always appending a tool_result, which Anthropic rejects as MODEL_CALL_FAILED. Return { error } so the pairing stays intact.
…runGithubToolStep` returns `{ error }`, and `listPullRequestFilesToModelOutput` calls `.map` on that object, throwing `TypeError: files.map is not a function` inside model-output formatting.

This commit fixes the issue reported at packages/github-tools/src/eve/steps.ts:28

## Bug

`runGithubToolStep` (`packages/github-tools/src/eve/steps.ts`) was changed to catch execute failures and return an error payload instead of throwing:

```ts
} catch (error) {
  return { error: error instanceof Error ? error.message : String(error) }
}
```

Both eve wiring paths pass the `execute` return value into `toModelOutput`:

*   `build.ts` (`buildEveToolDefinition` / `buildEveToolMap`): `toModelOutput: (output) => formatGithubEveToolOutput(name, output)`
*   `executeGithubEveTool` (used by `@github-tools/eve-extension`) returns the same `runGithubToolStep` result, which eve then feeds to `toModelOutput`.

`formatGithubEveToolOutput` (`registry.ts`) strips `rateLimit` then dispatches to a per-tool formatter. `stripRateLimit({ error })` leaves the object unchanged (no `rateLimit` key). For `listPullRequestFiles` it dispatches to `listPullRequestFilesToModelOutput` (`core/model-output.ts`):

```ts
export function listPullRequestFilesToModelOutput({ output }) {
  const files = output as ListPullRequestFilesOutput
  return { type: 'json', value: truncatePatchFields(files) } // files.map(...)
}
```

**Trigger:** any failed `listPullRequestFiles` call (e.g. GitHub 404/403, network error). The failure produces `output = { error: '...' }`, an object, so `truncatePatchFields(files)` → `files.map(...)` throws `TypeError: files.map is not a function`. This throws *inside model-output formatting*, re-breaking the tool loop and defeating the whole point of returning a payload (preserving `tool_use`/`tool_result` pairing).

The other array formatters (`getCommit`, `compareCommits`, `getPullRequestContext`) guard `files` with a ternary, and `getFileContent` guards with `'content' in result`, so `listPullRequestFiles` is the one that crashes on the top-level payload. (The others would still return an error payload verbatim, but wouldn't crash.)

## Fix

Short-circuit in `formatGithubEveToolOutput` — the single dispatch point shared by all paths — when the (rate-limit-stripped) output is an `{ error: string }` payload, returning it as `{ type: 'json', value }` without running the success-shaped formatter:

```ts
if (isErrorPayload(stripped)) {
  return { type: 'json', value: stripped }
}
```

`isErrorPayload` matches a non-array object with a string `error` field. This is safe because none of the GitHub tool success outputs carry a top-level `error: string` field. Typecheck (`tsc --noEmit`) passes.


Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
Co-authored-by: HugoRCD <hugo.richard@vercel.com>
@HugoRCD
HugoRCD merged commit 5bbcab1 into main Aug 26, 2026
14 checks passed
@HugoRCD
HugoRCD deleted the fix/eve-tool-error-result branch August 26, 2026 09:50
@github-actions github-actions Bot mentioned this pull request Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant