Repository navigation
fix(next): discover exported agents without loading scripts - #28
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
pranaygp
added a commit
that referenced
this pull request
Oct 23, 2026
Explicit top-level help writes to stderr, and `sandbox --help` exits with an error. Print `--help` and `-h` to stdout with exit 0 at both levels, matching the existing leaf commands. Invalid commands retain stderr and exit 1; invoking without arguments keeps its existing behavior. Fixes #17. Validation: - CLI subprocess regression: four expected failures before the fix; all 12 cases pass afterward. CLI/Vercel integration tests: 32 passed. - Workspace typecheck, changesets, public hygiene and host-spawn lint pass. Package build, local `check-dist`, and built CLI smoke checks pass. Linux CI typecheck includes the full release gate and passes. - Combined with #26, #27 and #28: all package suites pass (2,047 tests), plus 24 scripted AI SDK example tests and nine CLI-check tests; workspace typecheck/build/distribution checks pass. One optional live-model example failed its workspace-tool status assertion; its scripted suite passes without live credentials. CI typecheck/release gate, hygiene, local/Postgres/optional CLI checks, security, automated review and deployments pass. The full test job remains red in unchanged `harness-world/src/budget-boundary.test.ts:86` (extra `tool:5`), matching the failure on current main at ca4c420 in run 39885581630. The combined checkout passes all 374 kernel tests. This PR changes only CLI help handling, subprocess tests and a patch changeset.
Merged
pranaygp
pushed a commit
that referenced
this pull request
Oct 23, 2026
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## durable-harness@0.0.1 ### Patch Changes - [#10](#10) [`9b1ed08`](9b1ed08) Thanks [@chadhietala](https://github.com/chadhietala)! - Agent Runs tracing (`agentRuns()` from `/instrumentation/otel`) records sessions with `@vercel/agent-runs@0.0.1`, the library eve uses: a turn per prompt, a step per model call with the tool calls it asks for under it, in the schema Agent Runs reads. A turn that goes on in a later invocation (out of time, a crash, a wake, a lane handoff) stays one turn, its checkpoint kept with the session. A session's `traceAudience` decides what its spans record (`public`: inputs and outputs; anything else: metadata only), and `agentRuns({ capture })` changes that per audience; `exportPolicy` and `filteringProcessor` are removed. Claude Code, Codex and OpenCode record each model request through the Gateway with its prompt, reply and usage. Recovery applies the current capture policy to restored operations, keeping newly private content out of checkpoints and exports. Recorded tool definitions exclude provider credentials, untraced proxy requests stream without buffering, and tracing failures cannot change agent results. Checkpoint waits are bounded without discarding final updates after a soft budget expires or a write slows down; queued follow-ups retain their own turn identity. Agent Runs is an optional peer with inlined declaration types. Tracing requires Node.js 24 and optional tracing peers; other entrypoints retain Node.js 22 support. - [#25](#25) [`9f42806`](9f42806) Thanks [@pranaygp](https://github.com/pranaygp)! - Explicit CLI help prints to stdout and succeeds at every command level, including sandbox. - [`0bb39d7`](0bb39d7) Thanks [@pranaygp](https://github.com/pranaygp)! - First release: durable coding-agent harnesses on a Workflow SDK World. Claude Code (`durable-harness/claude-code`), Codex (`/codex`), OpenCode (`/opencode`) and Pi (`/pi`) each run as an agent whose session is a workflow run, its event log the source of truth: every model and tool call is a step in the log, so a crash anywhere resumes the turn from the log on another machine, and a tool that is not safe to rerun comes back to the model as interrupted instead of running twice. Claude Code and Codex run only in the session's own Vercel Sandbox (`workspace: sandbox()`, the default): the CLI runs in a VM per session with the session's Drive at `/workspace`, holds no credential (the Function makes its model calls, within the session's `sandbox({ budget })`), and a session restarted on a new VM keeps its files and resumes from the log. Both are tool-less by default: the app's tools are the only ones the CLI is offered; `builtins: true` turns its own tools on in the VM, each call in the log before it runs. `durable-harness/sandbox` deletes a session's VM and Drive (`deleteSessionSandbox`), cleans up idle ones (`sandboxCleanup`, opt-in), and prepares the base snapshot ahead of time (`npx durable-harness sandbox prepare`); a public chat route for such an agent needs `allowPublicSandbox: true`. OpenCode is tool-less too, starts no process and reads no file of the machine that drives the session for the model, and never changes the process's environment (so it runs beside libfx's agents in one process); `workspace: virtual()` on `opencode()` gives it its own shell, read, write, edit, patch, glob and grep (OpenCode's own tool code, names and schemas) on a virtual workspace, each call's file changes committed with its result, never on the Function's disk (`builtins` narrows them); `workspace: sandbox()` runs the same tools in the session's own Vercel Sandbox, its files on the session's Drive, the VM booted at the first call that needs it. A turn whose installed OpenCode or `effect` isn't the pinned version fails with both versions and the install line. Each agent has a streaming chat route (`agent.chatRoute()`, with an `authorize` check required in production). For apps already built on Pi 1.0's own durable `Harness` (pi-durable), `durable-harness/pi-durable` adds to your code instead of replacing it: open the storage with `openWorldStorage()` where you opened SQLite, JSONL or memory storage, register how a session is reopened with `resumeWith(open)`, and if the process dies mid-turn a wake reopens the session and Pi finishes the turn; `CodingTools` and `env: virtualEnv()` from the same module run Pi 1.0's own coding tools on a virtual workspace, each call's file changes committed with its result, never on the Function's disk, and `env: sandboxEnv()` runs them in the session's own Vercel Sandbox, its files on the session's Drive, armed with the session's own fencing token; a chat route, a shared Harness per session and a read-only follower are optional helpers. `withDurableHarness` (`/next`) sets up the queue's route for Next.js and also serves libfx's durable agents (several, each with its own `name`, with libfx 0.0.14 and later); `/vercel` does the same for Vercel Functions. Self-hosted on world-postgres or world-local, a process that starts the World without making agents (a worker of its own) forwards durable-harness's queue to the app's flow route with `forwardQueue(world)`. Sessions show up in Vercel Agent Runs with their model and tool calls (`agentRuns()` from `/instrumentation/otel`, with OpenTelemetry's SDK installed next to it: optional peers, which nothing else loads), pi-durable's included: a `traceAudience` on `openWorldStorage()` or `resumeWith()` says who sees their content. Pi is tool-less by default; `createCodingTools(virtual())` from `/pi` gives it Pi's own `read`, `bash`, `edit` and `write` (pi-coding-agent's names, schemas and descriptions) on a virtual workspace, or with `createCodingTools(sandbox())` in the session's own Vercel Sandbox (Pi stays in the Function, the VM is attached on the first call), and `pi()` refuses pi-coding-agent's own tools, which run on the host. Also included: documents (typed JSON state per session, `defineDoc`) and example workspace tools (`/tools`) on a virtual workspace (`virtual()`): not real Linux, and nothing of the machine that drives the session (its shell runs in a worker thread leased to that session alone, with an empty environment and a time limit per command), its files in the log, or with `virtual({ durable: false })` in memory for one turn. For libfx's own durable agent (`createFxAgent`), `durable-harness/fx` adds libfx's kernel tools on a virtual workspace (`tools: [...fxTools(virtual())]`): fx's names and schemas, each call's file changes kept with the session and never applied twice; `fxTools(sandbox())` runs them in the session's own Vercel Sandbox, armed with the libfx lease of the worker that runs the call, so a server that was taken over runs nothing more there. Experimental: patch releases only while on 0.0.x. - [#11](#11) [`31c87e8`](31c87e8) Thanks [@chadhietala](https://github.com/chadhietala)! - libfx's own durable agents show up in Vercel Agent Runs: `createFxAgent({ hooks: agentRunsHooks() })` with `agentRunsHooks` from `durable-harness/fx` records each libfx turn, its steps with their model calls, and its tool calls and the approvals they wait on, from libfx's semantic hooks (libfx 0.0.14 and later). A turn libfx yields, pauses or hands to another worker stays one turn, continued by the execution that resumes it in any process. Handed-off and fenced turns stay open for recovery; actual user interruption and cancellation finish the turn. Interrupted tool and approval identities are checkpointed so final cleanup also settles recovered calls the engine does not rerun. Execution IDs isolate overlapping deliveries, and ended session bookkeeping is released. Capture follows policy, hook failures use the tracing error handler, and provider/reasoning metadata and turn ordering are preserved. Unawaited hooks and checkpoint flushing remain best-effort. - [#26](#26) [`7b2a18d`](7b2a18d) Thanks [@pranaygp](https://github.com/pranaygp)! - Discard interrupted Pi-durable streaming partials before sending their replacement answers on reconnect. - [#27](#27) [`ff32c13`](ff32c13) Thanks [@pranaygp](https://github.com/pranaygp)! - Pi signals when a recovered reply replaces interrupted streamed text, retaining completed text from the turn. - [#28](#28) [`a5c24a1`](a5c24a1) Thanks [@pranaygp](https://github.com/pranaygp)! - Discover exported agents from source syntax without importing scripts or code samples into the generated flow route. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automatic Next.js agent discovery matched imports and calls inside docs strings and standalone scripts, adding those files to the flow route and executing their top-level work during builds.
Parse JS/TS/TSX and follow real imported factory bindings to values exported from module scope. Preserve import aliases, default and named exports, containers and accessors for existing agents, static class registration, effect-only Pi opener registration, explicit
agents, and mixed FX/harness modules. Document the explicit option for custom factories and registrations.Fixes #20.
Validation:
pnpm install --frozen-lockfileandpnpm typecheckpnpm --filter durable-harness test: 422 passed, 12 skipped; an earlier virtual-workspaceStorageFencedfailure passed both its isolated rerun and the full rerunpnpm --filter durable-harness build && pnpm --filter durable-harness check-dist(Linux-only relay caller authentication remains a CI check; local checks run on macOS)CI note: the first run stopped in the unchanged Codex R7 compaction test (expected
the code word is heron, receivedcompacted). Its isolated rerun and full Codex package rerun pass locally (58 passed, 1 skipped). The follow-up head passes CI: full monorepo tests (including the exact R7 regression), typecheck, public hygiene, and all local/Postgres/optional CLI lanes. The Vercel CLI lane is skipped by CI configuration; both app preview deployments succeed.