Skip to content

v1.0.36

Choose a tag to compare

@github-actions github-actions released this 24 Jul 04:46
· 4209 commits to main since this release

@veyyon/ai

Fixed

  • Fixed tool-call arguments for a string | number field being coerced to a number when the model sent a quoted numeric string (for example "123"), which changed the argument's type and lost data such as leading zeros ("007" became 7). A value that already satisfies its schema is now left unchanged; the numeric-string coercion still applies to number | null fields, where the raw string matches neither branch.

@veyyon/coding-agent

Changed

  • veyyon update now prints Checksum verified after it validates a downloaded binary against its published .sha256 sidecar, so you can see the integrity check ran and passed rather than only hearing about it when it fails. This matches the verified sha256 confirmation the curl installer already prints. The automatic startup update stays silent to avoid corrupting the session UI.

Fixed

  • Error messages no longer show a doubled Error: prefix. A failure while adding, removing, updating, installing, uninstalling, linking, or toggling a plugin or marketplace, applying a personality, or changing the Mermaid rendering setting now reads Failed to …: <reason> instead of Failed to …: Error: <reason>.
  • veyyon update --check --force on an already-up-to-date install now reports Up to date at X; --force would reinstall it instead of printing Forcing reinstall of X and then exiting without reinstalling anything. Check mode installs nothing, so the message now matches what the command actually does.
  • A failed release-binary download now reports the URL, the HTTP status, the requested version, and the missing asset instead of the bare Download failed: Not Found. A 404 explains that the version may not exist or its build for your platform was not published and points at veyyon update --check; a 403/429 gives the rate-limit retry hint. This most helps installing a specific older version, where a mistyped or unpublished version previously failed with no clue what went wrong.
  • A keybindings.yml/.json that parses cleanly but is not a mapping (a top-level sequence or a bare scalar) is now quarantined and left at defaults instead of silently corrupting the user's map. Such a file previously reduced a scalar to an empty map and turned a sequence into bogus index-keyed bindings, which the migration writer then persisted over the original file. A blank or comments-only file still loads as an empty config with no complaint.
  • A settings file that parses cleanly but is not a mapping (a top-level YAML sequence, a bare scalar, or a string) is now preserved and reported instead of silently discarded. The loader previously collapsed any non-mapping root to an empty config with no signal, so a mis-edited settings file erased the user's whole configuration invisibly. Such a file is now quarantined and surfaced through quarantinedFiles, exactly like an unparseable one, while a blank or comments-only file stays silent as a legitimately empty config.
  • The apply_patch default filesystem now commits crash-atomically. The interactive editor already wrote through the crash-atomic LSP path, but the default filesystem behind programmatic and SDK apply_patch callers still used a truncate-then-stream Bun.write, so a crash mid-write could leave the target file truncated. Create, update, and move writes through the default now write a sibling temp and rename it over the target, preserving an existing file's permission bits.
  • A file move that overwrites an existing destination is now crash-atomic and mode-preserving, matching the edit/write path. The destination was previously written with a truncate-then-stream Bun.write, so a crash mid-move could corrupt the file being overwritten; it now writes a sibling temp and renames it over the destination, carrying the destination's permission bits forward.
  • Edits and writes now commit crash-atomically. The file was previously written with a truncate-then-stream Bun.write, so a crash, SIGINT, out-of-memory kill, or full disk mid-write could leave your source file truncated or empty. It now writes a sibling temp file and renames it over the target, so an interrupted write leaves either the whole old file or the whole new one. The existing file's permission bits (including a script's executable bit) are preserved across the write, and a write through a symlink keeps the symlink and updates its target.
  • The CLI no longer hangs while printing a fatal error whose cause chain forms a cycle. A wrapped error whose cause pointed back at itself (directly or through another error) made the cause walk loop forever; it now stops at the first repeat and notes the circular reference.
  • The Windows installer no longer destroys local edits in the source checkout. A source update ran git reset --hard, and uninstall deleted the checkout outright, so local edits under ~/.veyyon/src (an edited AGENTS.md) were lost. It now commits any local changes to a veyyon-local-<timestamp> branch before updating, moves an existing tree aside to <dir>.bak-<timestamp> instead of deleting it before a fresh clone, and refuses to delete a checkout that holds unpushed work on uninstall. This matches the protection the POSIX installer already had.

Security

  • The self-updater now verifies a downloaded release binary against its published .sha256 sidecar before installing it, the same fail-closed integrity gate the curl and PowerShell installers already enforce. Previously veyyon update and the automatic startup update downloaded and swapped the binary with only a post-install --version check, which catches a wrong-version binary but not a corrupted or tampered same-version one. A missing, unparseable, or mismatched checksum now aborts the update and removes the partial download instead of installing something unverified.

@veyyon/hashline

Fixed

  • NodeFilesystem (the shipped disk-backed default) now writes crash-atomically. writeText and the content form of move stream into a sibling temp file and rename it over the target, so a process death mid-write (SIGINT, OOM kill, full disk, power loss) leaves the user's source file whole rather than truncated. An existing file's permission bits and a symlinked target are preserved.

@veyyon/mnemopi

Fixed

  • BankManager.renameBank now validates the source bank name, not only the destination. Every other bank operation rejects a name containing a path separator or .., but rename validated only the new name, so a source name like ../outside escaped the bank store and silently moved an out-of-tree directory into it. Both names are now validated before any filesystem change.
  • Content-addressed blob storage now writes crash-atomically. storeBlob wrote the extracted blob straight to its final sha256-named path with writeFileSync, so a crash mid-write left a truncated file whose bytes no longer matched its name; the existsSync fast-path then treated that corrupt blob as present forever and every reader silently got wrong bytes. The write now goes through a sibling temp and rename, so a blob is always either absent or the exact correct bytes.
  • The one-time legacy triples-database migration now copies crash-atomically. It wrote the old database into its new location with copyFileSync, which streams bytes into the destination, so a crash mid-copy left a truncated SQLite file that the existsSync guard then treated as a completed migration, silently losing the triple store. The copy now goes through a sibling temp and rename, so the destination only ever appears as the whole, valid database.

@veyyon/utils

Added

  • Added atomicWriteFilePreservingMode: an atomic write that carries the target file's current permission bits forward instead of stamping the 0o600 default (a new file gets 0o644). Use it when overwriting an existing file whose mode must not change, such as a source file an editor rewrites or a script that must stay executable.
  • Added splitReadSelector, stripReadSelector, and the READ_SELECTOR_RANGE_LIST_SRC grammar fragment: the one shared owner of the read-tool path-selector grammar (file.ts:50-200, :raw, :conflicts, and range:raw compounds). This grammar was previously hand-duplicated across packages with "keep in sync" comments; consolidating it here removes the drift risk.

What changed

41 commits since v1.0.27.

Features

  • feat(update): confirm 'Checksum verified' on a successful self-update

Fixes

  • fix(errors): remove remaining doubled 'Error:' prefixes; generalize the source-lock
  • fix(plugin-cli): stop doubling the 'Error:' prefix in plugin command errors
  • fix(update): honest --check --force message when already up to date
  • fix(update): verify self-update binary checksum, fail closed (parity with installers)
  • fix(update): rich release-binary download-failure message
  • fix(settings-test): drop wrong SettingPath cast that broke the release typecheck
  • fix(mnemopi): validate the source name in renameBank to close a traversal
  • fix(keybindings): quarantine wrong-shape keybindings files instead of corrupting the map
  • fix(settings): quarantine wrong-shape settings files instead of dropping them silently
  • fix(hashline): crash-atomic NodeFilesystem writes
  • fix(mnemopi): migrate the legacy triples database crash-atomically
  • fix(mnemopi): write content-addressed blobs crash-atomically
  • fix(coding-agent): make apply_patch default filesystem crash-atomic
  • fix(coding-agent): make file moves crash-atomic; hoist mode-preserving atomic write
  • fix(coding-agent): commit edits and writes crash-atomically
  • fix(install): remove a partial binary download on failure (Windows)
  • fix(cli): guard fatal-error cause walk against circular cause chains
  • fix(ai): stop over-coercing string|number tool args to numbers
  • fix(install): preserve local src edits on Windows update/uninstall (parity with install.sh)

Refactors

  • refactor(slash-commands): drop unnecessary 'as SettingPath' casts
  • refactor(utils): one owner for the read-tool selector grammar

Tests

  • test(atomic-write): allowlist hashline's deliberate node:fs-only temp+rename
  • test(ai): give heavy idempotence property tests explicit timeouts
  • test(ai): cover in-flight slot release when a provider request fails
  • test(ai): lock global idempotence of validateToolArguments on valid input
  • test(install): extract + cover the Windows checksum verification path
  • test(install): fix ps1 backup-branch discovery (scalar-index bug) and make it robust

Build & CI

  • ci(test): give packages/ai a 20s per-test timeout floor
  • ci: assert the published binary reports the release version (all platforms)
  • ci: verify get.veyyon.dev serves the install script post-deploy (curl|sh regression guard)
  • ci: verify the published Windows binary runs (install channel had no release verification)

Chores

  • chore: bump version to 1.0.36
  • chore: bump version to 1.0.35
  • chore: bump version to 1.0.34
  • chore: bump version to 1.0.33
  • chore: bump version to 1.0.32
  • chore: bump version to 1.0.31
  • chore: bump version to 1.0.30
  • chore: bump version to 1.0.29
  • chore: bump version to 1.0.28

Full Changelog: v1.0.35...v1.0.36