read tool and Anthropic builder derived an image's media type from its
file extension, so a .png file containing JPEG bytes was declared
image/png. Anthropic sniffs the real bytes and 400s the whole request
on a mismatch, breaking the session and making it impossible to resume.
- read tool now sniffs the real format from magic bytes (sniffImageMIME)
- Anthropic request builder reconciles declared MIME against the actual
bytes on every outbound image, repairing already-persisted sessions on
continue/resume
- kitty renderer re-encodes non-PNG images to PNG (f=100 is PNG-only),
fixing empty image boxes for JPEG/GIF screenshots
#38: emit OSC 7 (ESC ]7;file://host/path) on TUI setup and /cd so
terminals like kitty open new tabs/splits in the launch cwd instead of
inheriting a stale extension-subprocess directory. Verified end-to-end
against kitty 0.46.2.
#39: stop blanket-rejecting cd into subdirectories of the sandbox root.
CheckCommand now resolves the cd target and rejects only real escapes.
Add Sandbox.DisplayPath to present jailed tool-result/error paths
relative to root, reducing the absolute-path bias that pushed the model
toward unjailing.
Enabling the kitty keyboard protocol for Shift+Enter made terminals
report Esc as CSI 27 u, which the CSI-u parser dropped as KeyUnknown,
so Esc stopped aborting the agent. Map kitty control codepoints
(Esc=27, Tab=9, Backspace=127/8) back to their dedicated keys.
A long provider error (e.g. a Bedrock 400 with an embedded JSON body)
was appended as one line and clipped at the terminal edge. Wrap v.Err to
the build width via wrapLine (which hard-breaks unbreakable blobs), keep
the marker on the first row, and indent continuation rows so the whole
message is readable.
On VS Code's xterm.js the transcript is taller than the viewport, so an
in-place clear (home + erase-to-end) only wipes the visible rows and the
scrolled-away part lingers in retained scrollback, stacking a duplicate
on the next full repaint.
- Clear() (Ctrl+L) now emits \x1b[3J under keepScrollback to actually
drop that scrollback, then homes and repaints. Accepts VS Code's
viewport-snap since the user explicitly asked for a clean screen.
- Overlay close (esc on a dialog, slash/file popup dismissal) now runs
the same Clear() so closing a picker purges the stale overlay rows
instead of leaving them in scrollback.
- Resize() does the same purge under keepScrollback; previously it
skipped the wipe and left a half-repainted old-width frame until the
user pressed Ctrl+L.
Other terminals keep their no-snap clear path.
- Shell escape: typing "!cmd" runs it via the bash tool's shell in the
session cwd, honoring the /jail sandbox. Output is parked below the
transcript as a styled terminal-log block until the next prompt or
/clear, so it never enters the model conversation. Shares busy state
with the agent: esc cancels it and no turn or other escape can start
while one is in flight.
- VS Code terminal: full repaints used \x1b[2J, which xterm.js scrolls
into scrollback and duplicates the frame. Clear in place via cursor
home + erase-to-end under keepScrollback; Clear()/Resize() no longer
eagerly wipe. Force a viewport-safe Invalidate on slash/file popup
open and close transitions there.
- Restore the live tool-call overlay behavior (keep in-flight boxes
visible until the tool_result reaches the transcript) and drop the
forced repaint at turn start.
- Document the shell escape in the README.
- User themes from $ZOT_HOME/themes/*.json with partial overrides
(colors, syntax, spinner) and dark/light fallback.
- /settings color-theme picker; selection persisted in config.json.
- Theme-only extensions: extension.json plus theme.json (or
themes/theme.json) load without spawning a subprocess.
- write-zot-themes built-in skill and docs/themes.md.
- README, extensions docs, and embedded docs index updated.
Single Go module, four top-level packages under packages/. Import
paths become github.com/patriceckhart/zot/packages/<name>; downstream
consumers can depend on individual packages without pulling the rest.
Layout:
packages/provider/ LLM clients + catalog
packages/provider/auth/ credential store + OAuth + login server
packages/core/ agent loop, sessions, cost
packages/tui/ terminal toolkit + chat view
packages/agent/ CLI wiring, system prompt
extensions/ extproto/ modes/ tools/ skills/ swarm/
sdk/ (was pkg/zotcore, package renamed zotcore -> sdk)
ext/ (was pkg/zotext, package renamed zotext -> ext)
internal/ and pkg/ removed. The internal/assets logo moved into
packages/provider/auth/assets.
Public Go SDK identifiers renamed:
pkg/zotcore (package zotcore) -> packages/agent/sdk (package sdk)
pkg/zotext (package zotext) -> packages/agent/ext (package ext)
This breaks Go-based extensions and embedders; the JSON wire protocol
for extensions and RPC is unchanged, so non-Go extensions, already-
built extension binaries, and zot rpc consumers are unaffected.
Docs, examples, and the built-in write-zot-extension skill updated
for the new paths and identifiers. Shadow-bug fixes in code samples
(ext := ext.New -> e := ext.New).