Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/prune-authoring-surface.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eve": minor
---

Remove loader-only guards, event framing exports, deprecated code-extension GitHub/computer-use aliases, and legacy audience auth fields. Built-in and code-extension grep now share bounded modes and workspace containment; import named callback/config types from their authoring entries, and move PR-watch imports from `eve/extensions/code/prwatch` to internal `eve/internal/code/prwatch`, passing `{ connector, org }` as `readPullRequestWatchSnapshot`'s second argument.
26 changes: 19 additions & 7 deletions docs/code-extension.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ Configure `github` to broker GitHub access through Connect instead. The extensio
| `github.org` | With `github` | Organization whose repositories the `gh` tool can access |
| `github.broker` | With `github` | `broker(sandbox, rules)` callback that installs, then removes, the GitHub credential rules |
| `github.authorize` | No | `authorize({ auth, repository, token })` callback that allows or denies each `gh` tool invocation |
| `github.attribution` | No | `attribution(ctx)` callback that returns the `{ name, email }` co-author for this turn |
| `github.attribution` | No | `attribution(ctx)` returns the current turn's `{ name, email }` co-author, or `null` |

The `gh` tool requests a token scoped to exactly one repository in `github.org` for each invocation. The sandbox process receives a placeholder `GH_TOKEN`, and the firewall exchanges it on matching GitHub requests. Your `github.broker` callback receives the header-transform rules for the command, then `null` to remove the lease. The callback must preserve your other network rules. GitHub authentication has no command-delivery option.

Expand Down Expand Up @@ -129,22 +129,34 @@ export default git({
});
```

Commits made by the `gh` tool are authored by the GitHub App. To credit the person a turn works for, return them from `github.attribution`. The callback receives the tool's context, so it can read the verified caller from `ctx.session.auth.current` or resolve their linked accounts with `ctx.getToken`. The `gh` tool then ends every `gh-signed-commit` message, and every `gh pr create` body passed with `--body` or `--body-file`, with `Co-authored-by: <name> <email>`. Return `null` to publish without a co-author. `Co-authored-by` lines the agent writes itself are kept, and the trailer joins their block so they still count. Pull requests created without a body flag, such as with `--fill` or `--template`, and other paths, such as `gh api`, are not attributed.
### Credit the person behind a turn

```ts
git({
Commits made by the `gh` tool are authored by the GitHub App. Return a verified user mapping from
`github.attribution` to add that person's `Co-authored-by` trailer to `gh-signed-commit` messages
and `gh pr create` bodies passed through `--body` or `--body-file`. The callback receives the tool
context, including `ctx.session.auth.current` and `ctx.getToken`. Return `null` to omit attribution.
Existing co-author trailers are preserved; commands without a body flag and direct `gh api` calls
are not attributed.

For example, resolve the author through your application's authenticated user mapping:

```ts title="agent/extensions/git.ts"
import git from "eve/extensions/git";
import { brokerGitHubLease, coAuthorFor } from "../lib/github";

export default git({
github: {
connector: "github",
connector: "github/my-agent",
org: "acme",
broker,
broker: brokerGitHubLease,
attribution: (ctx) => coAuthorFor(ctx.session.auth.current),
},
});
```

### Migrate from `code({ github })`

`code({ github })` is deprecated. While it is set, the code extension still contributes `code__gh`, its GitHub instructions, and the signed-commit `code__pr` skill. Without it, the code extension contributes no GitHub tool, instructions, or pull request skill. Move the `github` option to `git({ github })`, and import `gh` and the GitHub sandbox helpers from `eve/extensions/git/tools` and `eve/extensions/git/sandbox`.
`code({ github })` is rejected. Move the `github` option to `git({ github })`, and import `gh` and the GitHub sandbox helpers from `eve/extensions/git/tools` and `eve/extensions/git/sandbox`.

## Prepare the sandbox

Expand Down
13 changes: 12 additions & 1 deletion docs/concepts/built-in-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,8 @@ Remove the file to remove the tool. `disableTool()` is unnecessary because `glob

### `grep`

`grep` searches sandbox file contents with a regular expression. Add it:
`grep` searches files inside the sandbox workspace. It is also the implementation of the code
extension's `code__grep` tool. Add it:

```sh
eve add tool/grep
Expand All @@ -424,6 +425,16 @@ export default defineTool({

Remove the file to remove the tool. `disableTool()` is unnecessary because `grep` is not added by default.

Inputs are `pattern`, optional `path`, `glob`, `ignoreCase`, `literal`, `context`, `limit`, and
`outputMode`. `files_with_matches` is the default and lists paths; `content` returns matching
lines and `count` returns per-file totals. Identifier-like patterns use literal matching unless
`literal: false` is explicit. The default limit is 50 rows, capped at 200, with additional byte
and line bounds. Relative paths resolve inside the workspace; parent traversal and symlinks
outside it are rejected. Ripgrep respects `.gitignore`; the POSIX fallback does not.

Results contain `content`, `matchCount`, `outputMode`, `path`, and `truncated`. Use
`outputMode: "content"` when migrating a caller that previously expected matching lines.

### `no_reply`

`no_reply` ends the turn without a reply. Use it when a scheduled check finds nothing to report, or when an action the agent already took is the whole answer. The model calls it with an optional `{ reason }`, which stays in the session history and traces and is never sent. The turn completes without a final message, so channels and schedule sends post nothing, and later turns see that the agent chose to stay quiet. Add it:
Expand Down
4 changes: 2 additions & 2 deletions docs/reference/typescript-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ Tool definitions accept `availableInSubagents: false` to restrict the tool to to
| `eve/instrumentation/otel` | `otel`, `otelIntegration`, `localTraces`, `agentRuns`, OpenTelemetry policy types |
| `eve/local-dev` | `getLocalDevCapability`, `LocalDevCapability` |
| [`eve/models`](../guides/decide) | Automatic model selection with `auto` |
| `eve/models/openai` | `openai`, `chatgpt`, deprecated `experimental_chatgpt` |
| `eve/models/openai` | `openai`, `chatgpt` |
| `eve/models/anthropic` | `anthropic` |
| [`eve/ai`](../guides/decide#decide-inside-a-tool) | Standalone `decide` |
| `eve/evals` | `defineEval`, `defineEvalConfig`, `mockModel`, eval types |
Expand Down Expand Up @@ -182,7 +182,7 @@ export default defineAgent({
});
```

Pass another bare OpenAI model slug to override the default. `experimental_chatgpt()` remains as a deprecated alias.
Pass another bare OpenAI model slug to override the default. The retired `experimental_chatgpt` alias is not exported.

`chatgpt()` uses stateless requests (`store: false`). eve retains reasoning summaries and encrypted reasoning in session history and replays them after tool calls and on later turns. You do not need to configure `reasoning.encrypted_content` explicitly.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default defineEval({
await t.send(
[
`Use the write_file tool to create the file ${FILE_TOOLS_PATH} with exactly this content: ${FILE_TOOLS_TOKEN}`,
`Then use the grep tool to search for ${FILE_TOOLS_TOKEN} under /workspace.`,
`Then use the grep tool to search for ${FILE_TOOLS_TOKEN} under /workspace with outputMode content.`,
"Reply with the matching line verbatim.",
].join("\n"),
);
Expand Down
4 changes: 2 additions & 2 deletions packages/eve-code/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ Before writing code, read the installed eve package docs for extensions, hooks,
## Boundaries

- Connector UIDs enter through extension config. The authentication hook resolves Vercel app tokens before each turn.
- GitHub instructions, the `pr` skill, and the `gh` tool belong to `@eve/git` (`eve/extensions/git`). The deprecated `github` config keeps `code__gh`, `code__pr`, and the GitHub instructions through `extension/lib/github-compat.ts`, which imports `eve/extensions/git/sandbox`; add no other GitHub or pull request content here.
- GitHub instructions, the `pr` skill, and the `gh` tool belong to `@eve/git` (`eve/extensions/git`). The removed `github` config is rejected; do not add GitHub or pull request contributions here.
- Consumers with non-Connect credentials may call `authenticateGitHub` or `authenticateVercel` directly from their sandbox lifecycle.
- Broker credentials without placing them in model-authored URLs or arguments.
- Use real `git`, `gh`, and `vc` CLIs rather than bespoke repository lifecycle tools.
- Keep `apply_patch` as the only extension-owned file editing primitive.
- Keep shared implementation under `extension/lib/`; filesystem paths define contribution names.
- Computer use lives in `@eve/computer-use` (`eve/computer-use`). Keep the deprecated computer-use re-exports in `extension/lib/sandbox.ts` until they are removed; do not add computer-use code here.
- Computer use lives in `@eve/computer-use` (`eve/computer-use`). Import its public helpers directly; do not add computer-use code or re-exports here.

## Build and publish

Expand Down
9 changes: 4 additions & 5 deletions packages/eve-code/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ It ships inside the `eve` package. This private `@eve/code` workspace package is

- `eve/extensions/code`: the extension
- `eve/extensions/code/sandbox`: sandbox bootstrap and credential helpers
- `eve/extensions/code/tools`: `apply_patch` and `grep` (`gh` is a deprecated re-export)
- `eve/extensions/code/prwatch`: PR-watch primitives for consumer-owned workflow tools
- `eve/extensions/code/tools`: `apply_patch` and `grep`

## Mount

Expand All @@ -21,9 +20,9 @@ export default code({
});
```

Both connectors are optional; `code({})` mounts without either. The Vercel connector requests an app-subject token. Firewall delivery is the default and keeps tokens outside sandbox processes; without a consumer `broker`, it requires a sandbox provider that exposes `setNetworkPolicy()` and fails otherwise. Use `delivery: "command"` on the Vercel connector for providers without mutable network policy. A top-level `broker(sandbox, rules)` callback lets the consumer merge Vercel credential rules into its own network policy.
The Vercel connector is optional; `code({})` mounts without it. The Vercel connector requests an app-subject token. Firewall delivery is the default and keeps tokens outside sandbox processes; without a consumer `broker`, it requires a sandbox provider that exposes `setNetworkPolicy()` and fails otherwise. Use `delivery: "command"` on the Vercel connector for providers without mutable network policy. A top-level `broker(sandbox, rules)` callback lets the consumer merge Vercel credential rules into its own network policy.

The `github` option is deprecated; configure it on `eve/extensions/git` instead. While it is set here, this extension still contributes `code__gh`, its GitHub instructions, and the signed-commit `code__pr` skill. Without it, this extension contributes no GitHub tool, instructions, or pull request skill.
The retired `github` option is rejected. Configure `eve/extensions/git` for GitHub tools, instructions, and the pull request skill.

The read-only worker subagent defaults to `openai/gpt-5.6-terra-fast` with `xhigh` reasoning. Set `worker: { model, reasoning, openaiReasoningEffort? }` to choose another model; `openaiReasoningEffort` is passed to OpenAI models as `reasoningEffort`.

Expand All @@ -48,7 +47,7 @@ export default defineSandbox(() => environment.open());

eve derives the prepared environment generation from the sandbox file and environment options, not from imported helpers, so upgrading eve alone does not rebuild an existing prepared artifact.

Computer use lives in `eve/computer-use`. Mount it next to this extension when the sandbox has a desktop. `installComputerUse`, `startComputerUse`, and `COMPUTER_USE_REVALIDATION_KEY` are still re-exported from `eve/extensions/code/sandbox`, and `computer_use` from `eve/extensions/code/tools`, but both are deprecated.
Computer use lives in its own extension. Import its tools and sandbox helpers directly; the deprecated code re-exports are removed.

Preparation ensures `gh`, installs wrappers for `gh`, `vc`, and `gh-signed-commit`, and installs TypeScript diagnostics. With `eve/extensions/git` configured for `github`, repositories requiring verified signatures use `gh-signed-commit` through its `gh` tool.

Expand Down
54 changes: 18 additions & 36 deletions packages/eve-code/extension/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,33 @@ import { defineExtension } from "eve/extension";
import type { SandboxSession } from "eve/sandbox";
import { z } from "zod";

import type { GitHubConfig } from "eve/extensions/git/sandbox";

export type CredentialPolicyBroker = (
sandbox: SandboxSession,
rules: Record<string, Record<string, string>>,
) => Promise<void>;

export type { GitHubLeaseRule } from "eve/extensions/git/sandbox";

export type GitHubLeaseBroker = GitHubConfig["broker"];
export type GitHubAttribution = NonNullable<GitHubConfig["attribution"]>;

const fn = <T>() => z.custom<T>((value) => typeof value === "function");
const delivery = z.enum(["firewall", "command"]).default("firewall");
const reasoning = z.enum(["provider-default", "none", "minimal", "low", "medium", "high", "xhigh"]);
const openaiReasoningEffort = z.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]);

export default defineExtension({
config: z.object({
/**
* @deprecated Mount `eve/extensions/git` with this `github` config instead.
* While set, this extension still contributes the authenticated `gh` tool,
* its instructions, and the signed-commit `pr` skill.
*/
github: z
.object({
connector: z.string().min(1),
org: z.string().min(1),
broker: fn<GitHubLeaseBroker>(),
attribution: fn<GitHubAttribution>().optional(),
})
.optional(),
vercel: z
.object({
connector: z.string().min(1),
delivery,
})
.optional(),
broker: fn<CredentialPolicyBroker>().optional(),
worker: z
.object({
model: z.string().min(1),
reasoning,
openaiReasoningEffort: openaiReasoningEffort.optional(),
})
.optional(),
}),
config: z
.object({
vercel: z
.object({
connector: z.string().min(1),
delivery,
})
.optional(),
broker: fn<CredentialPolicyBroker>().optional(),
worker: z
.object({
model: z.string().min(1),
reasoning,
openaiReasoningEffort: openaiReasoningEffort.optional(),
})
.optional(),
})
.strict(),
});
14 changes: 0 additions & 14 deletions packages/eve-code/extension/instructions/github.ts

This file was deleted.

15 changes: 0 additions & 15 deletions packages/eve-code/extension/lib/github-compat.ts

This file was deleted.

15 changes: 6 additions & 9 deletions packages/eve-code/extension/lib/prwatch-github.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { deleteTokenCacheEntry, getToken } from "@vercel/connect";
import { z } from "zod";

import extension from "../extension.ts";
type WatchGitHubConfig = { readonly connector: string; readonly org: string };

const GITHUB_API = "https://api.github.com";

Expand Down Expand Up @@ -220,9 +220,7 @@ function githubTokenParams(org: string, repoName: string) {
};
}

async function mintWatchToken(repo: string): Promise<string> {
const github = extension.config.github;
if (github === undefined) throw new Error("GitHub is not configured for this agent.");
async function mintWatchToken(repo: string, github: WatchGitHubConfig): Promise<string> {
const parts = repoParts(repo);
if (parts.owner !== github.org.toLowerCase()) {
throw new Error(`Repository ${repo} is outside ${github.org}.`);
Expand All @@ -234,9 +232,7 @@ async function mintWatchToken(repo: string): Promise<string> {
return token;
}

async function invalidateWatchToken(repo: string): Promise<void> {
const github = extension.config.github;
if (github === undefined) return;
async function invalidateWatchToken(repo: string, github: WatchGitHubConfig): Promise<void> {
const parts = repoParts(repo);
deleteTokenCacheEntry(github.connector, githubTokenParams(github.org, parts.name));
}
Expand Down Expand Up @@ -286,11 +282,12 @@ async function readPullRequestWatchSnapshotWithToken(

export async function readPullRequestWatchSnapshot(
input: PullRequestWatchInput,
github: WatchGitHubConfig,
): Promise<PullRequestWatchSnapshot> {
for (let attempt = 0; attempt < 2; attempt += 1) {
let token: string;
try {
token = await mintWatchToken(input.repo);
token = await mintWatchToken(input.repo, github);
} catch (error) {
if (!isRetryablePullRequestWatchError(error)) throw error;
throw new RetryablePullRequestWatchError(
Expand All @@ -301,7 +298,7 @@ export async function readPullRequestWatchSnapshot(
return await readPullRequestWatchSnapshotWithToken(input, token);
} catch (error) {
if (attempt > 0 || !shouldRefreshPullRequestWatchToken(error)) throw error;
await invalidateWatchToken(input.repo);
await invalidateWatchToken(input.repo, github);
}
}
throw new Error("Pull request watch token refresh exhausted unexpectedly.");
Expand Down
16 changes: 0 additions & 16 deletions packages/eve-code/extension/lib/sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,3 @@ export {
authenticateVercel,
type BrokeredCredentialOptions,
} from "./credentials.ts";

/** @deprecated Import from `eve/computer-use/sandbox` and mount `eve/computer-use`. */
export {
COMPUTER_USE_REVALIDATION_KEY,
installComputerUse,
startComputerUse,
} from "eve/computer-use/sandbox";

/** @deprecated Import from `eve/extensions/git/sandbox`. */
export {
executeGitHubShell,
githubShellApproval,
type GitHubLeaseRule,
type GitHubShellInput,
type GitHubShellOutput,
} from "eve/extensions/git/sandbox";
2 changes: 1 addition & 1 deletion packages/eve-code/extension/lib/tooling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
GH_SIGNED_COMMIT_SOURCE,
GH_SIGNED_COMMIT_VERSION,
GITHUB_TOOLING_PATHS,
} from "eve/extensions/git/sandbox";
} from "eve/internal/git";
import { shellQuote } from "./shell.ts";

export { GH_SIGNED_COMMIT_SOURCE, GH_SIGNED_COMMIT_VERSION };
Expand Down
Loading