Repository navigation
Releases: kmetia/kmet-agent
Release list
v0.2.0
v0.2.0 — the JVM Clojure host
kmet now runs on three hosts: Babashka (the primary one), native Jolt, and
JVM Clojure. Same source tree, same features, same extensions — plus a
platform-independent release artifact, a JVM test gate, and a JVM nREPL for
development. kmet --version in a source checkout reports the real version
again, and the model catalogs are refreshed.
JVM Clojure host
bb start-jvm # run the app under JVM Clojure
bb nrepl-jvm [port] # nREPL on the JVM classpath (default 7803)
bb test-jvm / bb test-ext-jvm # the full gate, on the JVM
bb test-changed-jvm / bb test-ext-changed-jvm # the changed-file loop, on the JVM
bb uberjar-jvm # target/uberjar-jvm.jar (java -jar …)
bb dist-jvm # dist/kmetc-<version>-jvm.zipRunning from a checkout needs the Clojure CLI;
the packaged artifact just needs a Java runtime (verified on JDK 21 and 25).
- A third host, named. Host detection learned the JVM: the welcome logo
readskmet (clojure)and the footer badge is now Кц beside Кб
(Babashka) and Кј (Jolt) — the Cyrillic transliteration of each runtime's
initial. kmetc, so all three install side by side. The JVM's command iskmetc
(Babashka keepskmet, Jolt keepskmetj). Its artifact is one uberjar plus
launchers —kmetc.jarwithkmetc,kmetc.sh,kmetc.bat,kmetc.cmd
andkmetc.ps1, all honouringKMET_JAVA_OPTS— so one zip serves every
platform with no cross-building. The jar is AOT-compiled behind the
kmet.agent.jvm-main:gen-classentry, carries the model catalogs, the
bundled extensions and a baked version, and every build ends with a smoke test
(--versionand--list-models) so a jar that assembles but cannot start
fails the build.- Extensions work the same way. Extension
:depsresolve in-process through
tools.depson this host (:jvmalias), and the bundled extensions are
staged under the same resource keys on every artifact, so an extension loads
from the same path on all three hosts. Clojure is pinned once (:clj-pin,
1.12.5) and the dev run, the test tasks and the packager all resolve through
it, so they cannot drift apart. - The clipboard works on Windows.
org.babashka/ffi— the standalone
extraction of Babashka'sbabashka.ffi— is now a JVM dependency, so
kmet.libs.clipboard-winis no longer Babashka/Jolt-only. It needs the
Class-File/FFM API of JDK 22+: the:jvmalias grants native access and the
jar repeats the grant as anEnable-Native-Accessmanifest attribute, so
java -jarneeds no flag. An older JVM still runs the app and falls back to
the platform tools. - JVM-only gaps closed. SCI evaluation and output binding in
run_code,
extensionui-customcomponents, andkmet.tui.core's protocol re-export
snapshots now behave on the JVM as they do on Babashka. - Dev nREPL ports are split per host: 7801 (
bb nrepl), 7802 (Jolt's
nrepl-server), 7803 (bb nrepl-jvm, writes.nrepl-port). The clojure
extension's port discovery probes 7801–7803 before the historical
7888/1667 fallbacks.
Downloads
| Host | Artifact | Run as | Needs |
|---|---|---|---|
| Babashka | kmet-<version>-<platform>.zip |
kmet |
nothing |
| Jolt | kmetj-<version>-<platform>-static.zip / …-dynamic.zip |
kmetj |
native libs only for dynamic |
| JVM | kmetc-<version>-jvm.zip |
kmetc |
a Java runtime |
Jolt zips now name their native link mode (-static / -dynamic, -dev
for dev builds): a static build is self-contained while a dynamic one needs its
native libraries on the host, so a release can carry both and tell them apart.
The executable stays kmetj — static and dynamic are two builds of one command.
Runtime and extensions
- One owned app tree. Every registry — tools, commands, hooks, skills,
prompt templates, renderers, transformers, flags, process stores — is mounted
on the app root and owned per registration. The root mounts before extensions
load and remounts on/reload. - Unloading disposes everything. An extension's
shutdownis followed by a
disposal pass over everything it registered and the resources it loaded,
contributed themes included — no leftovers after/reloador a runtime
unload. - New
/unitscommand. Lists registrations: every store owner (a
registry's address, an extension's registrations) with its keys, one flat line
each. It is engine-portable, so RPC clients get it too. - One ordered event bus. A single process-level registry with node-scoped
subscriptions: handlers run in registration order, and a node that is torn
down stops receiving. /compactmid-turn is deferred instead of dropped. Running it while the
agent works now queues the compaction and starts it when the turn settles;
the RPCcompactcommand answers{:accepted true :scheduled true}, the
extension:compactcapability reports through the caller's callbacks, and
session swaps or/newdrop pending requests.
Fixes
- Stealth models after a
/modelswitch. CommandCode's stealth endpoints
reject an assistant message with noreasoning_content(an empty string
included), so every request after a mid-session switch to
stealth/cat-jam:freeorreflection/beam:freefailed with a 400. Those
models now get the non-empty reasoning placeholder they require. run_codeandclojure_evalcall lines show the code. The tool call line
is the code itself (quiet mode shows the first non-blank line instead of a
bare prompt), and a script starting with a blank line no longer leaves an
empty line above the call.--versionin a source checkout reporteddevon every host; it reports
the real version again.- Extension
:terminatesurvives a scriptedrun_codecall and a hook that
blocks a call, instead of being dropped.
Models
- Model catalogs refreshed: new
deepseek-v4.1-flash-1017,minimax-m3.1and
step-5-previewentries, provider catalog updates (Bedrock, Cloudflare,
Hugging Face, OpenRouter, Qwen, xAI and more), and opencode'sspace-bunny
retired.
Under the hood
- The agent loop is split out of one namespace into
kmet.agent.loop.{state,message,compact,completion}, and the composition
runtime shrank to the store (kmet.libs.scope) and the node/stage mounting
inkmet.agent.runtime. - Module coordinates are renamed
kmetia/*→kmet/*; the Babashka uberjar
payload is nowtarget/uberjar-bb.jar, distinct from the JVM jar. - README and user docs describe the three hosts, their artifacts and their
tasks.
Full changelog: v0.1.3...v0.2.0
v0.1.3
v0.1.3 — 2026-10-17
219 commits since v0.1.2.
Highlights
- RPC mode — a headless front end for editors and scripts.
kmet --mode rpc
serves a session over EDN on stdin/stdout: one command per line, responses
correlated by an optional:id, events streaming in print mode's wire
projection. Clients prompt, steer, follow up, abort, clear queues,
open/switch/fork/clone sessions, read messages/entries/tree/stats, export
HTML, set model and thinking level, set the queue modes, compact, and list
commands. Extension dialogs arrive as:ui-requestrecords and are answered
with{:type :respond ...}(a timeout resolves the request's degraded
default); notify/status/widget/title/editor channels are fire-and-forget. A
thin client library (kmet.modes.rpc-client), a real subprocess
end-to-end suite, anddocs/rpc.md(with the pi parity
table) ship with it. - Print mode resumes sessions and can speak EDN.
-c/--continueand
--session <id|prefix|path>now work under--print, through the same
resolver the TUI uses; print sessions land in the cwd-encoded session dir,
so a print run can be continued later, and a resumed session keeps its
recorded working directory.--mode edn(implies--print) writes the
session header plus one EDN map per event,:message-updatedeltas only,
with exception payloads stringified so the stream stays readable. Print
consumes the runtime's event stream and settles from:agent-settled, so
aborted and failed runs report to stderr and exit non-zero. - Packages can come from git.
kmet install git:host/path[@ref](protocol
URLs and scp-like forms work too) clones into a managed checkout under the
scope'sgit/root, records the source verbatim, and validates the ref so a
crafted one cannot smuggle a git option.//subdirnames a package inside a
repository — several packages share one clone, each with its own settings
entry, identity, filters and config row.kmet update [source]fetches and
hard-resets (a pinned source to its ref, an unpinned one to the origin's
default branch);kmet removedeletes the checkout along with the last
entry that uses it. - A Tk GUI backend over an extracted, toolkit-agnostic hiccup engine. The
hiccup core moved out ofkmet.tuiintokmet.libs.hikap(.core,
.component,.alias) and reakt intokmet.libs.reakt.core, both
parameterized for other toolkits; the newkmet.tk.*backend renders the
same trees into Tk on both babashka and Jolt, with Tcl 9.1/9.0/8.6
loading, Tk paired to the interpreter's ABI, the classic (:tk/…) and
themed (:ttk/…) widget sets, an image layer, canvas items, context menus,
treeviews, grid/place, native dialogs, editable text, multiple windows and
the TUI theme as a dark ttk style set. App UI over it (:ui/…tags,
kmet.agent.ui.gui.transcript) and two demos
(bb scripts/demos/gui_tk_demo.clj,
bb scripts/demos/gui_tk_session.clj) land too; it is not yet wired to a
CLI launch mode. - The source tree is now a workspace of modules. Application code lives
undermodules/(agent,ai,libs,tui,loader,tk,reakt,
hikap), each a standalone classpath root, andmodules.ednis the single
workspace manifest every task reads — the test registry is derived from the
tree instead of hand-maintained, and guards hold the literalbb.edn/
deps.ednlists to it.modules/appbecamemodules/agentand the app
namespaces flattened underkmet.agent. - The session runtime is the front-end API.
kmet.agent.session-runtime
owns the wiring (agent state, system prompt, config-derived run options,
extension handle) and exposesprompt!/steer!/follow-up!/cancel!/
compact!plus a subscriber list with per-subscriber error isolation, so
the TUI, print, and RPC are all just subscribers; a layer guard now fails
any mode or UI namespace that reaches into the agent loop directly. - Registries are engine-scoped. Commands (with a pending buffer and no
fallback reads), custom tools and tool sources, extension event listeners,
input/before-agent-start hooks, tool-call/tool-result hooks, and markdown
transformers plus entry/message renderers are owned by the engine that
registered them — the ground work for multi-engine sessions. - Faster markdown and wrap paths.
md/parseon a 2 KB message drops
1408 → 278 µs (bb) / 1144 → 397 µs (jolt); a 17 KB prose line 27.2 →
1.64 ms (bb); perf.md 148.6 → 60.2 ms (bb). The wrap tracker and
truncate-to-widthrun the hand-rolled ANSI scanners on both hosts
(styled tracker line 40.5 → 4.2 µs jolt; a 300-char styled line truncated
to 100 columns 1630 → 93 µs jolt, 17.5×), and the bash/output sanitizers
share the scanner and skip the CR passes when there is no CR. - Newer models. Batch-priced entries across Anthropic, OpenAI, Google,
xAI and Qwen on Bedrock, Vertex and the gateways; Claude Fable 5/5.1,
Gemini 4 Argon, GPT-6.1 Sol, Muse Spark Open / Muse Wonder, Nemotron 3.5
Super VL, LFM2.5-24B-A2B, GLM-5.3-Flash Free and more on OpenRouter;
Together's catalog grows (Kimi K2.6 default, MiniMax M2.7/M3). The
opencode-godefault moves todeepseek-v4.1-flash(upstream retired
deepseek-v4-flash); several dead OpenRouter entries (Claude Opus 4,
Claude 3 Haiku, free previews) are dropped.
Upgrade notes
- Jolt floor is v0.8.22 (was v0.8.21). Several workarounds for now-fixed
Jolt issues are retired early, and self-contained builds carry the new
reaktandhikapmodules. - Source layout moved:
src/kmet/…→modules/<module>/src/kmet/…, and
the app namespace root iskmet.agent(kmet.app.*is gone). Extension
authors should follow the header docs;kmet.extensionis now
kmet.agent.extension,kmet.tui.hiccupiskmet.tui.hikap, and the
extracted libraries arekmet.libs.hikap.core/kmet.libs.reakt.core. opencode-go's default model isdeepseek-v4.1-flash. If your
settings.ednpins"deepseek-v4-flash", update it — the old id no longer
resolves.--modenow selects the non-interactive mode:text(print output,
the default),edn, orrpc. A valid--modewithout-pstill runs
non-interactively, and an invalid one exits 1.- Packages: local sources behave as before; git checkouts are managed
under~/.kmet/agent/git(.kmet/gitwith-l) and are never edited by
hand —kmet updateis the way to move one. A configured git package that
is not installed (or whose subdirectory is gone) is skipped with a warning
at load. npm sources and pi's--self/--modelsremain unported; bare
kmet updateis the all-packages form. - Headless safety is enforced: a guard walks the static require graph of
print and RPC and fails if either reaches the TUI, the app UI, or the Tk
backend (kmet.tui.themestays reachable through the extension ABI).
RPC mode
kmet.modes.rpcserves EDN commands on stdin and protocol records on
stdout; a malformed line answers a parse response without an id, and a
handler throw is that command's failure response — never the process's.
Stdin EOF disposes the engine.- Prompting:
prompt(pi's disposition rules),steer,follow-up,
abort,clear-queue,new-session,get-state. A prompt while a run is
active requires:streaming-behavior(:steeror:follow-up); steer and
follow-up reject:imagesinstead of dropping them silently. - Session:
get_messages,get_last_assistant_text,get_session_stats,
export_html,switch_session,fork,clone,get_entries,get_tree,
set_session_name. Model:set_model,cycle_model,
get_available_models. Thinking:set_thinking_level,
cycle_thinking_level,get_available_thinking_levels. Queue modes and
compaction:set_steering_mode,set_follow_up_mode,compact,
set_auto_compaction. Discovery:get_commands, filtered to:rpcand
source-tagged:extension/:builtin/:prompt/:skill. - The extension UI port forwards dialogs per front end with per-kind degraded
defaults, and a single-line/<name>dispatches through the same command
registry the TUI uses — portable builtins and extension commands answer
:handled(extension commands execute immediately, even mid-stream), while
unknown slash text stays an ordinary prompt. kmet.modes.rpc-clientis the scripted client (start/stop!,send!,
request!,on-event!,on-settle!,wait-idle!, stderr and unparsed
lines), exercised by a^:slowsuite that drives a real subprocess.
Print mode
- Shared session resolution: path-like args against cwd, otherwise an exact
id then an id prefix under the sessions base dir; an unmatched argument
reports to stderr and exits 1;--sessionwins over--continue.
-r/--resumestays TUI-only. --mode ednemits the session header and every event as one EDN map per
line throughevent-bus/wire-event, which drops the cumulative assistant
snapshot from:message-updateand stringifies error slots so a Throwable
never breaks a consumer.- The run's completion and exit code come from
:agent-settled; a throw in
the consumer delivers the failure before rethrowing, so the result promise
can no longer be left undelivered.
Packages
kmet installacceptsgit:host/path[@ref],#ref,https://,ssh://,
git://and scp-like forms; refs are validated against option injection.//subdir(directory or single file) makes a monorepo contribute several
independent packages over one checkout; a missing subdirectory fails before
anything is persisted, listing the checkout's directories, and a checkout
cloned solely for the failed install is removed again.- `kmet u...
v0.1.2
v0.1.2 — 2026-10-12
150 commits since v0.1.1.
Highlights
- The run lifecycle now tracks pi end to end. The two remaining boundaries
—:turn-endand:agent-before-settle— are actionable: a handler returns
session:entriesand:continue trueto extend the run, and:turn-end
hands over the persisted entry ids. A message queued from:agent-endruns
as a fresh attempt in the same prompt. A custom message sent while streaming
is held in a real pending queue until the turn's tool results are in, so it
can no longer land between a tool call and its result. - Append-only per-message context edits. A
{:role :context-edit ...}
entry omits or rewrites an earlier message for every future provider
request, while the raw session (usage totals, replay, the TUI) keeps the
original. - Compaction reliability. Summarization calls retry and report their
cause; the summary cap gains the session's thinking budget, so a
deep-thinking model no longer truncates (and fails) a summary; per-model
budgets land as:compact-model-overrides;:session-before-compactcan
cancel or supply the summary itself; a throwing summarizer ends compaction
cleanly. - A stalled provider can no longer hang a turn. The stream idle timeout is
120 s by default (was 300 s), the total request deadline is off by default,
and the wait for the response to start shares the idle deadline — a request
the provider accepts but never answers fails instead of leaving the spinner
running. Print mode honors the configured timeouts too. - Memory is reclaimed again. New
kmet.libs.weak:track!component
watches and reaction dependency watches are held weakly and swept, the
component drop sites dispose, and--debugprints a one-line
leak-survivor report after teardown. - Frames got cheaper and the spinner quieter. The spinner paints half as
many frames at the same revolution speed, bucket-paced drivers skip a wake
when a frame is already fresh, unchanged lines and whole passes are reused,
and the frame's cursor/normalize/diff walks are fused. Steady frames run at
~14 ms (bb) / ~12.5 ms (jolt) on a 2.6 MB transcript. - Windows and Jolt. The
powershelltool ships as a bundled opt-in
extension; session writes survive a Windows AV lock; path completion
understands drive and UNC paths. Jolt's floor moves to v0.8.21 and
jolt distnow defaults to the optimized fast-boot build. - Newer models. Claude Haiku 5.5 across Anthropic, Copilot, Bedrock, the
gateways and OpenRouter; Mistral Large 4, Codestral 25.08 and the Ministral
3 family; GPT-6.1 Sol/Pro batch entries; Nano Banana 2 Lite on Vertex.
Upgrade notes
run_codeis emit-only.(emit value)(orsandbox/emit) is the single
reported channel; stdout, stderr and the script's final value are captured
for the output budget but never reported. A script that printed or returned
its result must emit it.- HTTP defaults changed:
:http-idle-timeout-ms300000 → 120000,
:http-total-timeout-msnil (follow idle) → 0 (disabled). The idle timeout
now also bounds the response-start wait. Set both explicitly to keep the old
behavior. - Follow-up messages drain one at a time by default (
:follow-up-mode
:all→:one-at-a-time);:steering-modestill defaults to:all. /thinking <level>now persists the level as the session default, not
just the session's current value.- New
:default-toolssetting selects the built-in tools: plain names
replace the set,+name/-namemodify it, unset means all; extension tools
are unaffected. The config TUI now edits it and starts in project scope when
the project has a.kmet/dir. jolt distbuilds the optimized image by default (--opt);--release
produces the old backtrace-carrying binary and--devstays unoptimized.
The Jolt floor is v0.8.21 (was v0.8.16).bb slopscans source only by default;--testincludes tests.
Sessions and the agent loop
:turn-endfires after every turn — including an errored or aborted
response, where it precedes:agent-end— with the boundary state
(:context-entries/:context-messages, the projection-aware
:llm-messages,:pending-messages,:can-continue) plus
:message-entry-idand:tool-result-entry-ids. Returned:entriesare
appended in order ({:role :custom}is extension state;{:role :custom-message}also enters the context) and:continue trueruns one
more turn once the entries are committed and the context can back it
(dropped with a warning otherwise). Handlers on the same boundary see each
other's:entries/:continuemerged.:agent-before-settlefires once before the prompt settles, carrying the
same boundary state and the same return contract.- A message an
:agent-endhandler queues (viasend-user-messageor
send-message!with:trigger-turn) drains into a fresh attempt in the
same prompt; a second batch still queued is picked up by that attempt's own
poll. A send from:agent-settledstays queued for the next submission,
and cancelling clears the queues and ends the continuation. - Pending custom-message queue and
:next-turn(pi:_pendingCustomMessages
/_pendingNextTurnMessages): a message deferred while streaming is
appended once the turn's tool results are in, at every turn end and at the
settle boundary. - Append-only context edits:
{:role :context-edit :target-id <entry-id> :replacement nil | {:content ...}}omits or rewrites that earlier message
for future requests (a rewritten tool result keeps its call id, so the
call/result pairing survives). Only editable message roles on the active
branch are targetable; the projection changes, the session does not.
kmet.app.loop/append-context-edit!is the same operation outside a
boundary handler. - The post-run threshold compaction check runs from the settle path in both
the:settledand:errorarms, after the attempt's:agent-end; a
threshold compaction never retries the turn. - Tool calls outside the active set are rejected as
Tool <name> not found
(pi:prepareToolCall) instead of executing via registry lookup — a
disabled built-in or a hallucinated name can no longer run. agent-endreports the run's accumulated messages (pi:newMessages) and
re-bases when a mid-run compaction or:contextreplacement swaps the
context, fixing a stalesubvecthat settled completed turns as errors.- An abandoned attempt is omitted from the recovery context before the retry
backoff and overflow compaction; session switches recreate the runtime
selection from settings, as pi does. - Compaction and branch summaries: a successful compaction emits
:session-compactwith the appended rollup entry,:from-extension,
:reasonand:will-retry; the summarizer's error cause is carried through
instead of collapsed; retries are observable through
:summarization-retry-scheduled/:summarization-retry-attempt-start/
:summarization-retry-finished. - A cancelled summarization that had not started now returns
{:aborted true}
instead of racing a spurious "No API key" error.
Compaction and tokens
- The summarization output cap is
0.8 ×the effective reserve plus the
session level's thinking budget when the model reasons, bounded by the
model's max output (pi:adjustMaxTokensForThinking) — a deep-thinking
session no longer spends its whole allowance on reasoning and gets its
summary rejected aslength-truncated. :compact-model-overrides, keyed by the exact"provider/modelId", tunes
:reserve-tokens/:keep-recent-tokensper model with per-field fallback to
the ordinary setting (pi:compaction.modelOverrides) — a 1M-window model
can reserve room for its responses without changing every other model.:session-before-compactmay return{:cancel true}or supply the summary
itself with{:compaction {...}}(the entry then records:from-hookand
the events carry:from-extension); its payload gains
:custom-instructions,:will-retryand a projection-aware
:preparation.
HTTP and providers
- The response-start wait is bounded by the idle timeout (pi: undici
headersTimeout=httpIdleTimeoutMs), so a provider that accepts the
request but never responds fails retryably instead of waiting forever. - Idle default 120 s; total deadline disabled by default,
niltracks idle,
a positive value sets an independent deadline. Print mode builds its agent
with the configured timeout values (it previously let the defaults win
silently). - SSE stream chunks are handed off as batches instead of single bytes,
cutting per-chunk overhead on hot streams. - The Anthropic, Google and Vertex request builders now report payload
conversion and auth-token failures through the caller's promise instead of
capturing them in an undereferenced future (which left the turn hanging). - A stored opencode-go credential no longer overrides an explicit settings
:provider; onlyKMET_PROVIDERdoes. The deadstealth/space-bunny-alpha
canonical ref is gone. - New end-to-end coverage for the
google-generative-aistream path.
Tools
run_coderuns scripts on a full babashka surface: the sandbox copies the
host's loadedclojure.*/babashka.*namespaces (macros survive) and
babashka's class table, soclojure.pprint,java.io.*,System,
Throwableandfutureresolve as in a babashka script; the fixed bundled
extension set (rewrite-clj.*,cljfmt.*,edamame.core,
parinferish.core) is available in-process. kmet's own namespaces stay
blocked. Output is emit-only (see Upgrade notes); Jolt keeps its smaller
class surface.- pi's
powershellto...
v0.1.1
v0.1.1 — 2026-10-05
164 commits since v0.1.0.
Highlights
- MCP servers on both protocol eras. The
mcp-adapternow speaks the
stateless2026-07-28revision over streamable HTTP and stdio (discovery
probe,resultTyperesults, long-livedsubscriptions/listencatalog
streams,x-mcp-headerparameter mirroring) while keeping the legacy
2025-11-25handshake and the deprecated HTTP+SSE transport working. The
negotiated era is cached and re-probed when a server contradicts the hint. - Streamed session resume. The resume selector lists sessions
newest-first and fills rows as each file finishes, so a recent session is
selectable immediately instead of after the full scan. Closing or picking
a session stops the remaining work. Ctrl+Zsuspends kmet to the background on Unix;fgrestores the
terminal and the TUI. On Windows the chord reports the unsupported status.clojure_evaljoins the Clojure extension: evaluate code in a running
nREPL server, discovering the port from port files or by probing the
common ports.- Newer models. GPT-6 Sol and GPT-6 Luna are available and the Codex
provider now defaults to GPT-6.1 Sol.
Upgrade notes
- Dev commands were renamed:
bb run→bb start, andjolt run -m kmet.core→jolt start. - The built-in
scripttool is nowrun_code(tool name, namespace, UI
label, session vocabulary, and:run-code/*errors all follow). Any
extension or mode config referencingscriptmust be updated. - The Babashka floor is now 1.13.225.
- Jolt's minimum version now tracks the latest tagged Jolt release
(:jolt/min-versionindeps.edn). clojure.data.xmlis no longer in the shared host set; an extension
needing it declares a Maven dependency.
MCP servers (mcp-adapter)
- Modern
2026-07-28support over streamable HTTP and stdio:server/discover
probing,MCP-Protocol-Version/Mcp-Method/Mcp-Nameheaders, per-connection
subscriptions/listen,x-mcp-headerparameters mirrored intoMcp-Param-*
headers, and spec-invalid tool definitions dropped fromtools/list. - Legacy revisions
2025-11-25,2025-06-18,2025-03-26, and2024-11-05
via theinitializehandshake, with the negotiated revision carried on
later requests; the deprecated HTTP+SSE binding stays supported for
handshake-era servers with spec-correct SSE framing and no endpoint polling. - Authentication hardening: RFC 9728 protected-resource metadata and RFC 8707
resource indicators, RFC 9207 issuer validation, DCRapplication_type,
issuer-keyed credential store (v2 file migration; refresh never crosses
authorization servers), callback-redirect and authorization-state
validation, and hardened credential-store file/process handling. - Deterministic tool-name assignment from a single naming source.
- Internals: stdio transport now runs on
kmet.libs.jsonrpc(child killed on
close), JSON-RPC failures carry the request id in ex-data, and the stdio
listener runs onconcurrent/spawn.
Sessions and resume
- Listings stream newest-first with per-file progress; filters and search
apply while loading and the selection follows the chosen session by path. - Closing the selector or choosing a session stops an in-flight scan, and a
superseded load's late result is dropped. - Loaded rows and the cursor survive empty partial snapshots, and toggling
to an uncached scope no longer leaves the previous scope's rows on screen.
Terminal UI
- The dock was rebuilt around an ordered panel stack with one leaving verb
and a consistent close path for overlays. - Tool status lines are now opt-in (
:status true) and ride a tail line that
only changes its text color on settle, so a finished tool can no longer
dirty scrollback.bash,run_code, andclojure_evalopt in. - The live terminal size is a reactive ref: the config screen reflows on
resize and panel chrome follows theme switches. - Default theme palettes were aligned with pi's OKHSL palettes.
- Component disposal fixes (transient Markdown/Image blocks, the autocomplete
list,ExpandableText, chat-history placeholders and status lines) and a
bounded kill ring. - Fixes: ordered-list source numbering in Markdown, wrapped table-cell
borders, kitty image id reuse across reflows, and OSC 8 escape stripping in
the plain-text helper.
Tools and the agent loop
script→run_code, with the model-facing text aligned to the DSH
programmatic-tool-calling wording; full bash and code call lines render in
the transcript.- Parallel tool calls settle as each one finishes; timed-out partials are
kept and retry reasons reported; a cancel that lands before the active LLM
call is installed is delivered; escape aborts only the compaction. - Process-tree kills are parents-first in the ps-walk fallback.
Models and providers
- GPT-6 Sol and GPT-6 Luna added to Codex; Codex defaults to GPT-6.1 Sol with
pi's none-reasoning set; GPT-5.6 Sol costs corrected; catalogs regenerated. --generate-modelsnow fetches provider and image model catalogs into
~/.kmet/agent/; image-catalog generation is bundled intogenerate-models.- GitHub Copilot sends its dynamic headers on every Copilot wire.
/sharenow handles a successfully authenticated share.
Extensions
- Tool renderers can opt into the transcript tail status line with
:status true;state-result-nodesandrender-code-callare public renderer helpers. - Parallel batches:
on-tool-callhooks run sequentially during preparation,
whileon-tool-resulthooks run per tool and may overlap. - Print-mode extension contexts are wired to the running agent;
:model-select
records and resolvedModelrecords are returned from contexts, and
:scoped-modelsresolves toModelrecords. - The extension UI registry is cleared when a mode ends.
- Dependencies: cljfmt 0.16.6;
clojure.data.xmldropped from the shared set.
Clojure extension
- New
clojure_evalnREPL tool, with port-file discovery and common-port probing. clojure_paren_repairis now strictly delimiter-only (no reformatting).- The shape validator accepts the full
defngrammar, multi-line docstrings,
and cross-type inserts.
Jolt and Windows
- Jolt floor tracks the latest tagged release; the v0.8.15 java.time and
file-URI fixes are adopted and their workarounds retired;/quitshuts the
agent pool down so Jolt exits cleanly;pack-extension!runs on Jolt. - Windows/WSL: WSL bash alias detection for
-sstdin, taskkill process-tree
kill, POSIX chmod guards, and normalized test paths.
Developer workflow and docs
- Duration and deadline measurement is unified on a monotonic clock, with a
guard test pinning the rule. - Attribution enforcement (commit-msg hook and CI) blocks AI attribution in
commits and PR text. - Changed-file tasks: lint dependency closure closed and ignored directories
never walked; a SOCKS-proxy test race fixed. - Docs: pi built-in tools reference added, Jolt/Windows ticket tracking
updated, andscripts/documented in the project layout.