Skip to content

Releases: MrCipherSmith/keryx

v0.2.67

Choose a tag to compare

@github-actions github-actions released this 24 Aug 12:54

[0.2.67] — 2026-08-24

Added

  • A suggested next step after every settled turn (Claude-style): when the
    main agent finishes and the queue is empty, a short model-generated follow-up
    appears in the composer placeholder. Tab / Right-arrow inserts it without
    submitting; Enter on the empty composer submits it directly; typing dismisses
    it. Fail-closed: no credential, a timeout, or a . reply shows nothing and
    never blocks the shell.

  • keryx workspace dismiss-candidate <evidence-path|session-id> — UNBOUND
    candidates (wrap-up ran with no workspace bound) can now be dismissed instead
    of lingering in catch-up / /review forever: the artifact is removed and a
    *-unbound-dismissed.json receipt is written, after which both the internal
    and external-slate readers skip it.

Fixed

  • /theme switch did not repaint already-rendered chrome. Only the
    chrome's own surfaces were recolored; transcript frames, tone block headers,
    dock buttons and sidebar panels kept the old palette's hexes, so dark-to-dark
    switches looked like the theme never applied. The tree is now walked with
    theme-color remapping (OpenTUI stores colors as RGBA objects).

v0.2.66

Choose a tag to compare

@github-actions github-actions released this 24 Aug 10:10

[0.2.66] — 2026-08-24

Fixed

  • A typed message in front of a paste vanished from the transcript, leaving
    only [pasted N lines].
    The composer's submit echo collapsed ANY
    multi-line input into that bare placeholder, so typing a question and then
    pasting a block after it discarded your own words entirely — the transcript
    looked like you'd said nothing. It now keeps your own first line and
    summarizes only the rest as a paste count (explain this [+ 12 pasted lines]). The logic was also duplicated between the chat and agent shells;
    it is now one shared function.

  • Fenced code blocks in a reply had no way to copy them. y//copy only
    ever reached the block-nav registry (thought/tool/output blocks) — a fence
    embedded in the reply text had no registry entry of its own, so there was no
    copy path at all. Both now fall back to the most recently rendered code
    block when nothing is registered to copy, and the block's header advertises
    the shortcut (python · 15 lines · y copy).

Added

  • Code blocks get lightweight local syntax highlighting. Comments,
    strings, numbers and keywords are colorized via a plain-string tokenizer —
    no tree-sitter worker, no network or grammar fetch, so it stays inside flow
    109's worker-free, no-egress rendering stance (D-2).

Known gaps

  • A paste can occasionally split — part of it lands in the transcript as
    a sent message, the rest stays stuck in the input. This traces to an open
    upstream bug in @opentui/core's StdinParser
    (anomalyco/opentui#1270,
    unterminated bracketed paste), present in both the installed 0.4.5 and the
    latest 0.5.7 — not fixable from here until it lands upstream.

v0.2.65

Choose a tag to compare

@github-actions github-actions released this 23 Aug 22:07

[0.2.65] — 2026-08-23

Fixed

  • /game's modal no longer scrolls as a whole and the board is never
    clipped.
    The 0.2.64 prompt card used flexGrow: 1 on a ScrollBox with no
    height cap, which made OpenTUI measure the card at the full parent height —
    the card ballooned to the whole modal body, pushed the stats/footer out of
    view and gave the modal a body-wide scrollbar that also clipped the bottom
    of the board. The agent panel now reserves a fixed slice (status + stats
    lines), the board is sized from the modal body HEIGHT (cell heights 2..5:
    tiny/small/medium/large), and the prompt card is a bounded minmax-style
    block (5..14 rows) that scrolls only inside itself. Board + panel now sum
    exactly to the body height, so everything is on screen at once on any
    terminal of ~30 rows or more.

  • The agent panel now shows what the model actually receives and with what
    parameters.
    The prompt card shows the system prompt AND the per-turn user
    prompt (the exact board state sent each turn, so you can see how the model
    learned your move); the status card shows the provider/model in effect
    (auto/auto until the first turn) and the compact last-turn/session stats
    (latency, in/out tokens, reasoning/fallback/error flags, fallback/error
    counts) on three lines instead of two tall cards.

  • Modal tab bodies got a stale 68x13 viewport instead of the real one. At
    mount time OpenTUI's width/height getters still return the last LAYOUT
    value (the 72x18 creation-time floor), so renderTab's context claimed the
    panel body was 68x13 even on a normal terminal — the /game board was sized
    from that floor. The host now computes the body size deterministically from
    the renderer (resolveModalPanelSize), matching the panel's actual resolved
    size at open.

v0.2.64

Choose a tag to compare

@github-actions github-actions released this 23 Aug 21:06

[0.2.64] — 2026-08-23

Fixed

  • /game's system-prompt card is no longer capped at 6 lines. The agent
    panel truncated the prompt the model sees to 6 lines plus "… (N more)" and
    left dead space below it. The card now renders the full prompt, flexes to
    absorb the leftover body height, and scrolls (wheel, scrollbar, or
    j/k/↑/↓ once the scrollbar has focus) when the prompt is taller than the
    space the layout leaves it.

v0.2.63

Choose a tag to compare

@github-actions github-actions released this 23 Aug 20:16

[0.2.63] — 2026-08-23

Changed

  • /game's agent panel is now real cards with a stats table. The system
    prompt, last-turn latency/tokens and session totals were one undifferentiated
    dim line; they are now three bordered cards — a status line ("agent is
    thinking…" / notice / "waiting for your move"), the system prompt wrapped as
    lines (capped at 6 + "… (N more)"), and a side-by-side last-turn/session table
    (model, first byte, total, in/out tokens, reasoning/fallback/error flags;
    turns, fallbacks, errors, token totals), with long provider/model ids
    truncated so a half-width card never clips. Footer hints now say
    arrows move / tab games.

Fixed

  • /game's left/right arrows stopped moving the cursor again. The
    multi-tab games-host split (0.2.62) dropped the onArrowKeys claim the
    legacy single-game modal keeps, so the modal host's own tab switch consumed
    both arrows and stopPropagation'd them before the game saw them — the
    cursor moved up/down but not sideways, and with one game the tab switch was
    a silent no-op. The games host now claims both arrows for the active game
    through the host's onArrowKeys hook again (a pure probe; the game's own
    keypress handler still applies the move, so each press moves once) and only
    falls back to tab switching when the game declines the key.

v0.2.62

Choose a tag to compare

@github-actions github-actions released this 23 Aug 19:32

[0.2.62] — 2026-08-23

Added

  • /game is now a multi-tab games host with an agent-stats panel.
    The single tic-tac-toe modal became a component-based games module
    (src/tui/games/): one GameDefinition contract (rules, prompts, render,
    input) plus a registry, so adding a game is adding one definition — its tab
    appears automatically on the shared modal host, with / switching
    games. Tic-tac-toe itself is split into core/prompts/layout/render/
    input/game. Under the board sits the new agent panel (dim/secondary):
    the exact system prompt the model sees each turn, plus per-turn
    latency/token stats — provider/model, time-to-first-byte, total time,
    input/output tokens, reasoning flag, local-fallback count, errors. runModelTurn
    now surfaces usage/latencyMs/reasoning from the stream so any caller
    can show what an agent turn actually costs.
  • /game <seconds> raises the model-turn deadline; the default went from
    12s to 60s.
    Local models are slow, and the stats panel's point is to
    observe that latency, not to race it. /game 45 sets a 45-second deadline
    for that modal.

Fixed

  • The sidebar now shows provider balance and session usage. A new
    Balance row under Model fetches the ACTIVE provider's balance live
    (DeepSeek GET /user/balance, OpenRouter GET /api/v1/credits — the only
    registry providers with public balance APIs; the rest render ), on
    mount and again on click, honouring KERYX_<NAME>_BASE_URL overrides. A
    new Usage row shows the cumulative in/out token totals for the session,
    fed from the same io.onUsage stream that drives the header counter.
    Both are wired into the agent and chat shells.

v0.2.61

Choose a tag to compare

@github-actions github-actions released this 23 Aug 00:20

[0.2.61] — 2026-08-23

Fixed

  • Web search returned empty results on bun-in-~/.bun installs. The
    bwrap profile for the sandboxed web worker masked $HOME entirely
    (--tmpfs), hiding process.execPath itself when bun lives under home.
    The worker could not start and the search bridge silently returned empty
    results. The profile now masks only home's secret subdirectories via
    defaultReadDenyList, leaving the runtime readable.

v0.2.60

Choose a tag to compare

@github-actions github-actions released this 22 Aug 23:57

[0.2.60] — 2026-08-23

Fixed

  • /game's cursor would not move left or right. modal-host claims both
    arrows for its own tab switch and calls stopPropagation(), so the game's
    keypress listener only ever saw up/down. The cursor now moves through the
    host's onArrowKeys hook, and left/right are removed from the keypress
    handler — that hook returns without stopping propagation, so handling them
    in both places would move the cursor two cells per press.

  • The board is sized from the modal body width: 9×5 cells where the 33
    columns they need fit, the previous 5×3 where they do not.

  • A model turn could hang the game indefinitely. There was no deadline on
    the provider call, so a stalled request left "agent is thinking…" on screen
    with R as the only way out. The turn now has a 12s deadline; on timeout —
    or on a reply that names no free cell — the game plays a local move (win,
    block, centre, corner) and says so, instead of silently passing the turn
    back and letting the user win against nobody. A hard error (no credential,
    provider failure) still hands the turn back with the reason. runModelTurn
    takes no abort signal, so a timed-out request is abandoned, not cancelled.

  • The model turn's output budget was 16 tokens. On a reasoning-capable
    model that budget covers the thinking pass, so the answer digit could be
    truncated away before it was ever emitted — the turn then looked like a slow
    model that skipped. Raised to 256; the visible reply is still one character.

  • The status line read "Your turn — O" while the agent was thinking. It now
    reads "Agent's turn — O".

v0.2.59

Choose a tag to compare

@github-actions github-actions released this 22 Aug 23:32

[0.2.59] — 2026-08-23

Fixed

  • /game drew its board as one 9-cell vertical column instead of a 3×3
    grid.
    The board was a single flexDirection: "column" box holding nine
    bare text nodes — with no row boxes between the board and the cells, flex
    put every cell on its own line. The tree is now built once in renderTab
    as three row boxes of three bordered cell boxes, and paint() only
    mutates the retained cell handles instead of clearing and re-adding all
    nine nodes on every keypress. The cursor is a real highlight (focus border

    • highlight fill) rather than a swapped glyph, the winning line takes the
      winner's colour, and legend/board/status are centred.
  • A model error during the game's turn was never visible.
    applyModelMove wrote the message straight onto the status node and the
    paint() immediately after overwrote it. The message now goes through a
    notice state that paint() owns and renders on its own line — the same
    line that carries "agent is thinking…".

v0.2.58

Choose a tag to compare

@github-actions github-actions released this 22 Aug 22:59

[0.2.58] — 2026-08-23

Added

  • /game — tic-tac-toe vs the model in a TUI modal. A pure game core
    plus a model move via an injectable, fail-closed provider factory; state
    lives in the modal's own closure so Esc minimizes without resetting and
    reopening /game resumes the same board. Available while the main agent
    is busy, registered alongside the other agent-only slash commands.

Fixed

  • The interactive agent's runaway-tool-loop guard counted unique
    tool-call signatures, conflating a big legitimate task with an actual
    loop.
    A task with many DIFFERENT tool calls (e.g. a wide refactor) was
    indistinguishable, under that metric, from real repetition, and hit the
    same budget wall either way. Replaced the three unique-signature pools
    (DEFAULT_MAX_TOOL_CALLS/_READ_/_NON_READ_) with a model-round-trip
    cap (DEFAULT_MAX_ROUNDS, KERYX_AGENT_MAX_ROUNDS); the existing
    per-signature attempt cap (MAX_ATTEMPTS_PER_HASH) remains the actual
    repetition guard. spawn_subagent and wiki deep-enrich child budgets
    migrated the same way.

  • Untrusted web content could permanently block an unrelated tool call
    turns later in the same session.
    Once any web_fetch/web_search
    result came back untrusted, every later non-read tool call was refused
    for the rest of the session, with no way back short of /new//clear
    including actions that had nothing to do with the tainted content. The
    gate is now scoped to the turn the untrusted content appeared in: it
    still blocks every later round within that same turn, but a following
    user turn starts clean.

  • External Slate-Adjacent Context (SAC) hands could get a workspace
    auto-created for them at close.
    Flow 200's lazy resolve-or-create in
    runWrapUp now excludes external slates entirely — a hand that never
    bound a workspaceId gets the unbound-candidate artifact, never a
    created workspace. Internal session/flow wrap-ups keep the lazy resolve
    (AC-38, flow 182).