Skip to content

OpenCode 2.2.1 skips AFT tools: Zod schema conversion fails on a.ref #1141

Closed

Description

@KomeijiReimu

What happened?

After upgrading OpenCode from 2.2.0 to 2.2.1 with @cortexkit/aft-opencode@0.62.0 enabled, the agent lost its file-editing and shell tools. OpenCode repeatedly logged:

Skipping invalid tool registration name=edit
error="Invalid tool definition edit: undefined is not an object (evaluating 'a.ref')"

The same error affected read, write, patch, shell and other AFT tools. Disabling AFT and removing the -opencode.tool.shell / -opencode.tool.patch entries restored the native tool plugins.

Expected: AFT tools remain available after the OpenCode update.

Environment and version change

  • Observed plugin version: 0.62.0.
  • Host: OpenCode 2.2.1 on Linux.
  • OpenCode 2.2.0 uses Zod 4.1.8; 2.2.1 uses Zod 4.6.7. Both use Effect 4.0.1.
  • The relevant OpenCode packages/core/src/tool/runtime.ts is identical in those two releases. Its JSON Schema conversion path falls back to the host's Zod converter when a schema has no Standard JSON Schema interface.
  • Current AFT main, 73c205629bd40301771992c38da2f0878746e46f (package version 0.63.1), still contains the override below. I checked the source there; the live failure was observed with 0.62.0.

Minimal reproduction

Install two Zod versions in a scratch directory:

npm install zod-old@npm:zod@4.1.8 zod-new@npm:zod@4.6.7

Run this as an .mjs file with Bun:

import { z } from "zod-old";
import { toJSONSchema } from "zod-new/v4/core";

const path = z.string().describe("File path");

// Same override as AFT's normalize-schemas.ts.
path._zod.toJSONSchema = () => {
  const original = path._zod.toJSONSchema;
  delete path._zod.toJSONSchema;
  try {
    const { $schema, ...schema } = z.toJSONSchema(path);
    return schema;
  } finally {
    path._zod.toJSONSchema = original;
  }
};

const input = z.object({ path });
console.log(toJSONSchema(input, {
  target: "draft-2020-12",
  io: "input",
}));

Result:

TypeError: undefined is not an object (evaluating 'seen.ref')
    at flattenRef (.../zod/v4/core/to-json-schema.js:397:13)
    at flattenRef (.../zod/v4/core/to-json-schema.js:444:13)
    at finalize (.../zod/v4/core/to-json-schema.js:470:13)

The same schema succeeds with the old converter. With the new converter, removing either the override or .describe() also succeeds. These controls isolate the failure to the described field's override interacting with the newer converter.

Cause and impact

normalize-schemas.ts:21-50 installs _zod.toJSONSchema on each argument to preserve metadata across Zod instances. In Zod 4.6.7, the override bypasses parent processing, but finalize still visits that parent. The missing entry in its seen map causes the exception.

AFT's assertV2Contract checks the schema with the plugin's own converter, so that check succeeds before the host's conversion fails.

registerAftTools removes the built-in read/edit/write/patch tools before adding the replacements. When OpenCode skips the invalid replacements, those tools are absent. The native shell/patch disable entries also remove those fallback plugins.

Proposed fix for discussion

Expose JSON Schema conversion through the V2 input schema's public Standard JSON Schema interface, using AFT's own converter while preserving validation and parameter descriptions. OpenCode already checks this interface before trying its own Zod converter. Keep the V1 behavior unchanged.

One focused regression for the described-field case, the existing V2 tool-surface checks, and an isolated OpenCode 2.2.1 run that exercises file editing and shell execution should cover this change.

Activity

  1. vladimirfx commented on Oct 29, 2026

    @vladimirfx

    This is block my pipeline. Is there a workaround?

  2. KomeijiReimu commented on Oct 29, 2026

    @KomeijiReimu
    ContributorAuthor

    @vladimirfx remove the plugin and wait for #1144 merged

  3. flyinghail commented on Oct 29, 2026

    @flyinghail

    2. This is block my pipeline. Is there a workaround?

    Same issue, waiting for an update.

  4. added
    design-approvedDesign agreed by a maintainer; a PR referencing this issue can be reviewed
    on Oct 29, 2026
  5. aft-alfonso commented on Oct 29, 2026

    @aft-alfonso

    Workaround until the fix ships: stay on OpenCode 2.2.0 (opencode upgrade 2.2.0) with AFT enabled. AFT 0.62.0 works there. We're merging #1144 and will ship it in the next AFT release.

  6. aft-alfonso commented on Oct 30, 2026

    @aft-alfonso

    Fixed in v0.63.4 by @KomeijiReimu's #1144. AFT's tools register again on OpenCode 2.2.1 and later. Update the plugin to 0.63.4; you no longer need to stay on OpenCode 2.2.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    design-approvedDesign agreed by a maintainer; a PR referencing this issue can be reviewed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions