Skip to content

v0.49.0

Latest

Choose a tag to compare

@github-actions github-actions released this 24 Jul 22:07

v0.49.0

One unified tool calling surface. This release consolidates every tool's parameters into a single convention, identical on OpenCode, Pi, and MCP — one file parameter name, one edit calling shape, 1-based indexing everywhere, and no routing knobs. Schema descriptions changed for most tools, so prompt prefix caches re-warm once after upgrading; there are no config changes and no manual migration steps.

One parameter name: path

  • Every tool that takes a file now takes pathread, write, edit, and the whole aft_* family (aft_zoom, aft_outline, aft_import, aft_refactor, aft_safety, aft_delete, aft_move, aft_callgraph). The mixed filePath/path split across tools was a documented source of model confusion (#165).
  • aft_callgraph's toFile is now toPath for the same reason.
  • The old spellings still work everywhere: filePath (and toFile) are accepted silently at every boundary — both plugins, the daemon transport, and MCP clients with cached schemas. They are simply no longer in the schemas. Supplying both spellings with different values is rejected rather than guessing.

One edit shape: edits[]

  • edit now has exactly three modes, one per call: edits[] (find/replace and line-range items), appendContent, or symbol + content. Mode conflicts and unknown parameters are rejected with errors that name the fix, replacing the old silent mode-priority ladder that made results hard to predict (#165).
  • The top-level oldString/newString form is gone from the schema but still accepted: it folds into a one-item edits[] internally. Pi-style oldText/newText item names and JSON-stringified edits arrays (a shape some models emit) are absorbed the same way.
  • Batch ambiguity errors are now actionable: when a find/replace item matches multiple locations, the response is ambiguous_match with numbered candidates (line and context for each) instead of a bare failure.

occurrence is 1-based

  • The occurrence selector on find/replace edits is now 1-based: occurrence: 1 selects the first match. It was the only 0-based index in a surface where lines, columns, and candidates are all 1-based, and production logs showed models passing occurrence: 1 to mean "the first match" and failing on exactly that. occurrence: 0 is now rejected with a clear message, and ambiguity candidates carry the same 1-based numbers, so the error and the retry finally agree.

aft_search routes itself

  • The hint parameter (regex / literal / semantic) is removed. Usage analysis across ~85,000 production searches showed forced lanes returned zero results at roughly 100x the rate of automatic routing (literal 21.8%, regex 23.2%, auto 0.2%) — mostly models forcing a lane with a query shaped for a different one, then abandoning the tool. Routing is now always automatic; a hint argument from older sessions is accepted and ignored.
  • Automatic routing gained a second chance: when the chosen lane finds nothing, the query is re-ranked by its terms through the hybrid index, and the result footer says so ([interpreted_as: literal; no exact match — ranked by terms instead]). Zero results after that means the content genuinely is not there.
  • grep is unchanged and remains the tool for explicit regex and exhaustive literal matching.

Trust corporate and custom certificate authorities

  • HTTPS requests (semantic-search embedding backends, URL fetching, binary downloads from the Rust side) now verify TLS through the operating system's trust store — macOS Keychain, Windows certificate store, and the standard Linux mechanisms including SSL_CERT_FILE. Corporate proxies with custom root CAs work without workarounds, and certificate failures are no longer retried as if they were transient network errors (#168).
  • Platform verification also avoids enumerating the system trust store on every request — on machines with large or unusual keychains, the previous approach could stall requests for seconds.

UI fixes

  • OpenCode Desktop and web now render edit diffs for files larger than the 512KB diff cap; previously those edits showed an empty diff panel. Edit and write results carry the same patch-based diff payload the native tools use.
  • Doctor and setup messages now show the correct npx @cortexkit/aft invocation instead of the bare aft, which pointed at the wrong binary (the Rust worker has no doctor command).

Compatibility

  • No action needed for existing configurations, indexes, or caches.
  • Agents notice exactly one behavior change: occurrence is 1-based, and occurrence: 0 is rejected with a message that explains the new indexing.
  • MCP clients get the same unified schemas; old argument spellings from cached schemas keep working.