Skip to content

v0.8.0

Latest

Choose a tag to compare

@maltyxx maltyxx released this 23 Sep 23:03
· 2 commits to main since this release
403451e

What's Changed

Everything a reply cost is now recorded with it and kept, and a conversation
can be exported as one JSON file — meant to be handed to a person, or to a
model, that knows nothing of SpecterChat. And what a request carries when
the conversation no longer fits the context window is now decided here,
rather than left to the server.

The database schema changed (v10). Updating from any released version
(0.5.0 to 0.7.3, all on schema v8) keeps your conversations, and the
database is copied before it is touched. But opening that database again
with a build older than this one erases it: those builds recreate
their tables whenever the schema version differs, in either direction.
Update the installed app rather than running both, and keep the copy this
version leaves beside it.

Added

  • Export a conversation as JSON. "Export (JSON)" in a conversation's
    menu, in the left sidebar, asks where to save and writes everything:
    every message with its reasoning, the tool calls with the arguments the
    model wrote, the tool results with the server's whole answer, the images
    as base64 (screenshots included), what each reply was generated with and
    measured at, totals per model, one entry per exchange, the current
    settings, and a guide explaining the app and what the model is actually
    sent. The API key and the MCP servers' headers are never exported.
  • Each reply records what it was generated with and what was measured,
    once and for good: the model and the server it went to, the sampling
    parameters (or the image options), the prompt and output token counts,
    the time before the first token, the reasoning time, the total duration,
    how the turn ended — finished, stopped, failed, or cut short by a crash —
    and what the server reported alongside its answer (finish_reason, usage
    details, llama.cpp timings). Kept in the database, so the numbers survive
    a restart and later settings changes.
  • The exact context of each request is recorded: the system prompt as
    sent, the MCP servers' instructions included, and the definition of every
    tool offered. Stored once and reused while nothing changes, so it costs
    almost nothing.
  • Tool results keep the server's whole answer, not just its text and
    images: structured results, _meta, per-item annotations and fields this
    version does not know about. Image bytes stay in their attachment, and the
    answer refers to them.
  • Each tool call records how long it took and which server ran it.
  • The line under a reply says what the exchange weighed: the tokens the
    request carried (↑ — the whole conversation, not just your last message),
    the tokens that came back (↓), and, when several turns answered you, the
    totals since your message (Σ) on the tokens as on the time.
  • What a picture weighs is now shown, in kilobytes: on the picture
    itself, at its top left corner, under the message you sent it with, in
    the line under a reply that returned one, and in the header of a tool
    result that took a screenshot — the last one without unfolding it. Token counts say
    nothing about the size of an image, and an image is most of what a
    conversation weighs.
  • Hovering the line under a reply spells every figure out in words and
    shows the detail: model, server, tokens sent and received, time to the
    first token, reasoning time, output speed, the reason the model stopped,
    and what the whole exchange has cost so far.
  • "Images Kept", in the right panel, says how many of the conversation's
    images travel with each request — globally or for one conversation. It is
    off by default: every image you sent goes out on every turn. Keeping only
    the last few makes sense for screenshots, which lose their value as the
    conversation moves on, and not for a conversation about three
    photographs, so you are the one who says which you are having. What is
    left out of a request is never removed from the conversation.

Changed

  • The speed shown under a reply is now the generation speed, measured
    from the first token, so reading a long prompt no longer drags it down.
    Expect higher numbers than before on conversations with a large context.
  • A stopped or failed reply keeps its duration and says so, instead of
    showing nothing.
  • The line under a reply reads as small icons rather than words —
    sent, received, weight, duration, speed, totals, time of day — so a
    longer line stays legible under the message. Every figure carries its
    unit.
  • Upgrading the database keeps your conversations. Until now, every
    schema change wiped the history; from this version on, each change is an
    incremental step, and every version ever released is on the same starting
    schema, so nobody loses anything on update.
  • The database is copied before it is migrated, next to itself
    (specter.db.v8.backup), once per schema it comes from. Delete it when
    you are satisfied the update went well.
  • A database written by a newer version is left alone. Instead of
    rewriting what it does not understand, the app sets it aside
    (specter.db.v11.newer) and starts a new one, so going back to an older
    version can no longer destroy a history.
  • The conversation is trimmed to fit the context window before it is
    sent.
    The whole conversation goes out on every turn — the protocol
    keeps nothing between requests — and until now, what happened when it no
    longer fitted was the server's business: a server that overflows forgets
    on its own, says nothing about it, and can cut a tool call away from the
    result answering it. The app now decides. A request carries the context
    length you set, less the room reserved for the answer, less a tenth.
    Images are left out first, one being worth a thousand tokens of the
    conversation that would be dropped to make room for it; what still does
    not fit costs whole exchanges, the oldest ones first. The exchange you
    are waiting on always travels, even when it is over the window on its
    own — sending it is the only way to find out what the server makes of
    it — and nothing is ever cut inside an exchange, so a tool call is never
    separated from its result.
  • What a request left out is recorded with the reply and written in the
    export (stats.droppedRuns, stats.droppedImages), so a short answer
    can be explained afterwards. The conversation itself is never rewritten:
    a trim shapes the request, not your history.

Fixed

  • A tool call the server sends without an identifier is no longer
    dropped
    , and two calls the server numbers alike are no longer merged
    into one — the first was lost.
  • Each tool result is written as soon as its call returns, instead of
    waiting for every tool of the turn: closing or losing the app no longer
    drops the results already obtained.
  • A reply whose tool calls were not all answered is no longer sent back to
    the server
    , which rejected the whole request and blocked the
    conversation.
  • A generated image is no longer sent back on the model's own turn. The
    OpenAI schema accepts an image only on a message you send, so a strict
    server refused the whole request and the conversation could not go on.
    The image now follows the turn that produced it in a message of its own —
    after the tool results, when that turn called tools — and "now make it
    blue" still edits it. Image servers keep the previous shape, which their
    protocol asks for.
  • The images of a turn that also called tools are no longer lost. That
    path never looked at them, so a model that generated a picture and called
    a tool in the same turn could not edit the picture afterwards.

Full Changelog: v0.7.3...v0.8.0