Repository navigation
Releases: michelebergo/nina.plugin.aiassistant
Release list
Release 2.5.10.0
Options page in tabs
Provider · Equipment control · Your rig · Advanced (external MCP servers, autopilot connection) · About - the shape of the Three Point Polar Alignment options page: a tab control that passes the mouse wheel on to NINA's page, each tab scrolling on its own. Nothing moved inside the sections; every button still sits next to the result line it writes to.
Model lists are now fetched once per page. WPF detaches the content of the tab you leave and raises Loaded again when you come back; without the guard, every return to the Provider tab would have meant six model-list requests.
Options page test
The page as WPF builds it from the XAML: tabs in setup order, every Test / Validate / Add / Reset button reaching exactly its own result line through the same tree walk the code-behind uses, each panel on the tab it belongs to, the controls surviving a tab switch. 157 unit tests.
Includes everything in 2.5.9.0 (Gemini tool calling fixed, one tool loop for all five providers, live contract tests).
Full changelog: CHANGELOG.md
Release 2.5.9.0
Gemini tool calling fixed
It had never worked. When Gemini called a tool, the result went back under a function role the API does not know, so every request that used a tool ended in a 400 after the tool had already run. Since 2.5.8.0 the external servers' full schema also reached Gemini with the type list ["boolean","string"] (sequential-thinking) that it refuses. Results now travel as a user content of functionResponse parts, and every schema type collapses to one JSON Schema word - the same normalisation OpenAI gets. Verified live with gemini-3.5-flash-lite: 193 tools declared, the tool called, the answer taken from its result.
One tool loop for all five providers
Anthropic, Gemini and Ollama now run the shared tool loop with a dialect of their own: how calls are read from a response, what is replayed before the results, how the results are written. The three providers lose 617 lines and keep only what is theirs - Claude's 90 s per-tool timeout and model fallback, Gemini's empty-answer diagnostics, Ollama's think: false. Claude now receives the external servers' full JSON Schema (arrays with items, nested objects) instead of a flat property map.
Live contract tests
dotnet test NINA.Plugin.AIAssistant.Test --filter Category=Live sends one real request per provider: the tools are declared, the model calls a bench tool whose schema has the shapes real servers write (type list, array without items, nested object), the result goes back in the provider's dialect, the model answers from it. Skipped unless the keys are in the environment and NINA is open with the Advanced API. Both Gemini defects passed every unit test and failed here; all five providers pass now (Mistral untested, no key). 142 unit tests.
Full changelog: CHANGELOG.md
Release 2.5.8.0
The newest OpenAI models call tools only through the Responses API. This release takes them there, automatically, and tidies what 2.5.7.0 built in a hurry: one tool loop for every spelling of tool calling, and Ollama on the same tool plumbing as everyone else.
Everything implemented in this release:
OpenAI Responses API, when a model asks for it
2.5.7.0 could only explain the problem: gpt-6-astra demands reasoning_effort: none before it will call a tool on chat completions, then rejects none. Those models call tools only through OpenAI's Responses API (/v1/responses).
Now the plugin listens for the model's own hint - "To use function tools, use /v1/responses" - stops negotiating parameters, switches that model to the Responses API and keeps it there for the rest of the session. Over that endpoint the same loop runs: the system prompt travels as instructions, the conversation as input items, the tool definitions in the flat shape the endpoint wants, and every output item the model produced - its reasoning included - is replayed before the tool results, because a reasoning model refuses a follow-up whose function call arrives without its reasoning. No temperature is sent there; the models that live on that endpoint refuse one.
Verified live with gpt-6-astra: a read-only "what is my equipment status?" switched once, then called nina_get_status, then wiki_search, then answered. gpt-4o, gpt-4.1 and the rest stay on chat completions, where nothing changes for them.
One loop, several spellings
The loop that asks the model, runs the tools it names, hands the results back and asks again is now written once (ToolLoop) and given the dialect of the API in use: how calls are read from a response, what is replayed before the results, how a result is written. Chat completions (OpenAI, Mistral) and Responses are the two dialects today. The next API is a formatter and a handful of tests, not another loop - and the loop is tested once, with scripted responses, for all of them.
Ollama on the shared tool plumbing
Ollama merged built-in and external tools with its own copy of the code since 2.4.1. It now uses the same MCPToolSources as OpenAI and Mistral: ninety duplicated lines gone, and an external server that declares a parameter with a list of types ("boolean" or "string") no longer reaches the model as a malformed schema. Ollama's own loop is untouched. Verified live: the status question went through nina_get_status exactly as before.
Full changelog: https://github.com/michelebergo/nina.plugin.aiassistant/blob/main/CHANGELOG.md
Release 2.5.7.0
Every provider can now drive your equipment. This release gives OpenAI and Mistral the tool loop they were missing, and teaches the OpenAI path to live with models whose rules the plugin has never seen.
Everything implemented in this release:
Equipment control with OpenAI and Mistral (closes #10)
Two hours after 2.5.6.0 labelled them "chat only", the limitation is gone. OpenAI and Mistral speak the same /chat/completions tool-calling dialect, so they share one loop: the model asks for tools, the plugin runs them against NINA through the Advanced API, hands the results back with the id of the call they answer, and repeats until the model answers in words. Same activity trace, same cancellation, same iteration cap as Claude, Gemini and Ollama.
Verified live with gpt-4.1: a read-only "what is my equipment status?" called nina_get_status and reported the disconnected devices without connecting anything - the acceptance test proposed in #10. Mistral's variant (its tool results carry the function name) is covered by the same tests.
Living with OpenAI's limits
128 tools per request. OpenAI refuses more, and the plugin carries 159 built-in tools plus whatever external servers you connected. The least conversational tools are left out first - rescans, device listings, one-by-one disconnects, readout variants, park positions, rotator mechanics, dome details, trained flats, framing setters - and only as far as needed. The tools the system prompt names, the wiki tools and your external servers are never dropped. The NINA log lists exactly what was left out on each request, and a test checks that the shipped catalogue fits without reaching the last-resort cut.
Parameters that change with every model generation. gpt-4o wants max_tokens and a temperature; the o-series want max_completion_tokens and no temperature; gpt-6-astra wants reasoning_effort set before it will call a tool. The plugin cannot carry the rulebook of a model released after it shipped, so it reads the 400 the model sends back, repairs the one parameter it names, applies each repair once, and remembers what worked for the rest of the session (reset when you change model).
Models that only call tools through the Responses API. gpt-6-astra demands reasoning_effort: none for tools on chat completions and then rejects none: it calls tools only through OpenAI's newer Responses API, which this plugin does not use yet. Instead of the raw JSON you now read a sentence saying so and which models to pick (gpt-4o, gpt-4o-mini, gpt-4.1) - or to turn MCP off to chat with it. Responses API support is the natural next step.
External tool schemas
An external MCP server that describes a parameter with a list of types ("boolean" or "string", as the sequential-thinking server does) or with no type at all used to break the whole request. One JSON Schema type word is sent now, the way every provider expects it.
Smaller things
- The "chat only" labels of 2.5.6.0 are gone with the limitation; the provider selector, the status line under it and the chat's welcome message describe what the chosen provider can do now.
- The short description in the plugin list finally mentions the Knowledge Wiki and equipment control on every provider; it had been left at its 2.5.2 wording.
- Under the hood:
IMCPCapableProviderreplaces the per-class casts that switched MCP on, so a provider that gains tools needs no change in the chat; 118 tests.
Full changelog: https://github.com/michelebergo/nina.plugin.aiassistant/blob/main/CHANGELOG.md
Release 2.5.6.0
This release is about telling you the truth before you spend money: which providers can drive your equipment and which can only chat, an options page laid out in the order you actually set things up, and an assistant that knows your own rig instead of guessing it.
Everything implemented in this release:
Chat-only providers say so (fixes #10)
OpenAI and Mistral have no tool calling in this plugin. That was always the case, but nothing on screen said it: with MCP ticked, the chat's first message promised equipment control for every provider, and a GPT-4o user learnt from the model itself that it "cannot access NINA" - after buying credits.
Which providers can drive NINA is now stated once in the code and read everywhere it matters. The provider selector labels OpenAI and Mistral chat only and the other three equipment control. The line under the selector says it. The OpenAI and Mistral sections say it. The Equipment control section, instead of disappearing with those providers, explains why it is unavailable and points at OpenCode for N.I.N.A. for anyone who wants an agent on their equipment with any provider and model. And the chat's welcome message says it - and updates when you change provider while the panel is open, instead of keeping the previous provider's promise on screen.
The README has a provider capability table to read before buying credits. Tool calling for OpenAI and Mistral is the next step and is tracked in #10.
The options page in the order you set it up
Like AI Weather's page since 1.15.14.0: AI provider (selector, key, Test, model), then Equipment control, then Your rig, then the advanced sections (external MCP servers, Autopilot connection), then About. Section titles and the theme's own colours for secondary text, so it reads in light and dark themes alike. The six lines of marketing at the top are gone - they belong on the plugin manager page, not above the settings. GitHub Models, retired by GitHub in July, is listed only for someone who still has it selected, so nobody's saved choice is rewritten and nobody else has to see a dead provider.
Your rig
A few lines from your active NINA profile now travel with each message: site coordinates and elevation, telescope focal length and ratio, camera pixel size and the resulting arcsec/pixel, and where images and sequence templates are written. Without them the assistant answered questions about your own equipment from general knowledge - which is to say, it guessed.
It is on by default. The exact text is written to the NINA log every time it changes, so you can always read what was sent, and one switch in Your rig turns it off for anyone who would rather not send coordinates and folder paths to a cloud provider. Ollama runs on your machine, so nothing leaves it either way.
The profile tool reads one section at a time
nina_show_profile used to answer with the entire settings tree of every profile - on a small local model that was one answer and no conversation left - and its description ("Show profile information") shared no word with any question a user actually asks, so among 150 tools it was never chosen. It now takes a section (telescope, camera, astrometry, imaging, ...), defaults to the active profile, and is described by what it holds.
Test buttons that tell you what went wrong
"Invalid API key: 429" sent people to check the one thing that was not wrong. The Test buttons now say what the status code means - key rejected, not permitted, model not found, rate limit or quota exceeded, provider down - followed by the provider's own message.
Under the hood
The plugin has its first unit test project (92 tests) covering the profile summary, the section filter, the error descriptions, the prompt composition, the provider capabilities, the welcome message and the status line.
Full changelog: https://github.com/michelebergo/nina.plugin.aiassistant/blob/main/CHANGELOG.md
Release 2.5.5.0
This release is about how the plugin presents itself: the mark you look for in the plugin list and the tab strip, the provider a brand-new installation opens on, and the text people read before they install it.
Everything implemented in this release:
One mark, in both places
The plugin looked like two different plugins depending on where you saw it. The old icon was white on a transparent background, so against a light theme it was there but invisible — you found the row by reading the name. The imaging tab strip carried a different drawing altogether: a bubble with a sparkle, where the plugin list showed a bubble with three dots.
Both surfaces now carry the same monochrome mark, and it reads on light and dark themes alike.
The tab icon's star used to punch a hole in the bubble. The tab mark is drawn as a geometry group, and a group fills by the even-odd rule: anything drawn inside an existing shape becomes a hole rather than an overlay. That is exactly how the three dots are made — they are meant to be holes. The star was drawn overlapping the bubble, so the overlap cancelled the same way, and what rendered was a star-shaped bite taken out of the bubble. The star now sits clear of the bubble, where it stays a star.
A new installation opens on Ollama
GitHub retired GitHub Models for all customers on July 30, 2026, and the plugin still defaulted to it. A fresh install therefore failed its very first message with an error telling the user to go and change provider — a bad first minute, and one where nothing on screen suggests which provider to pick instead.
New installations now open on Ollama: it is the only choice that needs no API key, and when Ollama is not installed the failure names a local address (localhost:11434), which points at a fix rather than at a dead end.
Nothing changes for anyone who has already chosen a provider. GitHub Models remains in the list, labelled Retired rather than Free, so an existing selection is never silently rewritten underneath you. The change applies to the stored default, to the configuration default, and to the fallback used when the setting cannot be read.
The usage readout fits a docked panel
The context and cost figures introduced in 2.5.4.0 were laid out for a wide panel. Crammed onto the title row next to the model name, the three groups of numbers collided with each other and were cut off — and the raw provider quota (11971000/12000000) was the loudest unreadable thing there.
They now sit on their own line, which wraps with the panel width, with each group labelled — three sets of token counts side by side mean nothing unless you are told which is which. The provider budget is shown in the same compact units as everything else: 12.0M rather than 11971000.
The description now describes the plugin
The text on the plugin manager page still described version 2.5.2: the Knowledge Wiki, the activity trace and the context and cost readout were missing from it entirely, and the retired provider was still listed as a search tag. Both descriptions and the tags have been rewritten against what the plugin actually does today.
Full changelog: https://github.com/michelebergo/nina.plugin.aiassistant/blob/main/CHANGELOG.md
Release 2.5.4.0
Automatically generated manifest for release 2.5.4.0.
This release is about seeing what the assistant is doing — and fixing three things that were hiding it.
Everything implemented in this release:
Activity trace in the chat
When the assistant uses tools to answer, you now see the work:
- While it runs: one line, updating in place, showing the step in progress with its arguments —
🔧 Calling: nina_slew_to_coordinates (target=M31, center=True). One line, not a growing list: the conversation stays on screen. - When it finishes: that line settles into a summary —
⚙ 3 tool calls— one click away from the full sequence. - Each call reports its outcome:
✓ ok (312 chars),✓ ok (empty result),✗ Guider not connected. A tool that failed and a tool that returned nothing used to be indistinguishable from one that worked, and the model does not always mention the difference. - Same trace from Claude, Gemini and Ollama. A question answered without tools leaves nothing behind — an empty "I worked on it" entry is noise.
- Even expanded, the trace scrolls inside its own box instead of pushing the conversation away.
Context and cost readout
The header now carries the numbers that matter over a long session:
- How full the context window is, as a bar that turns amber past two thirds and red past ninety percent. By then the oldest turns are about to be dropped, which is worth noticing before the assistant starts forgetting what was agreed earlier in the night.
- Tokens used and tokens left —
12.4k / 200k · 188k left. - Session totals and estimated cost —
session ↑34.2k ↓5.1k · ~$0.182.
The input tokens reported by the API are the real size of the context at that moment (system prompt, tool definitions and history included), so the percentage is measured, not estimated. The window sizes and prices come from a dated table matched by model-name prefix; a model the table does not know shows the token count and no bar rather than a reassuring percentage built from a guess. That deliberately includes every local Ollama model, whose context window is set by whoever wrote the model file.
The figures sit on their own labelled line that wraps with the panel width — three sets of token counts crammed next to the model name collided and were cut off in a docked panel — and the provider's rate-limit budget is shown in the same compact units (12.0M rather than 11971000).
Fixes
Changing the model no longer rebuilds the connection. Every settings write launched its own fire-and-forget re-initialization, and a single edit in the options writes several settings — up to eight ran concurrently with no ordering guarantee, so the configuration left active was the one that happened to finish last, not the one chosen last. The model id travels inside each request payload, so it is request data and not connection state: a model change now updates it alone, and every other trigger is coalesced into a single initialization behind a gate.
The chat header showed the previous model. It refreshed only when the provider changed, so picking another model of the same provider left the old name on screen — which is exactly what made a model change look like it had not been applied.
The "working" indicator covered the entire conversation. It shares the chat's row by design, floating over it, but had no vertical anchor: its background stretched over the whole message area, so for the length of every request the chat looked empty. It is now a strip anchored at the bottom.
Full changelog: https://github.com/michelebergo/nina.plugin.aiassistant/blob/main/CHANGELOG.md
Release 2.5.3.0
Automatically generated manifest for release 2.5.3.0.
Everything implemented in this release:
Knowledge Wiki — a local second brain for the assistant
- New file-based knowledge base at
%LOCALAPPDATA%\NINA\llmwiki: plain markdown, no embeddings, no database. Three levels following a Karpathy-style schema:raw/(append-only observations),wiki/(consolidated pages: entities, concepts, syntheses),SCHEMA.md(the spec), withindex.mdas the catalog andlog.mdas the chronology. - Seeded on first use with a starter pack: the schema, index, log, two entity page templates (equipment, observing site) and five troubleshooting concept pages (autofocus high HFR, plate-solve failures, guiding issues, meridian flip, backlash) — each with YAML frontmatter, a TL;DR and cross-links.
- Four new built-in MCP tools, inherited by every MCP-capable provider (Ollama, Anthropic, Google):
wiki_index— list all pages with their titleswiki_search— ranked full-text search with context snippetswiki_read— read a page (path-traversal safe, size-capped)wiki_append— record one fact into the append-onlyraw/daily notes
- The wiki tools work even without a NINA Advanced API connection.
- System prompt policy: the assistant searches the wiki BEFORE answering questions about the user's specific equipment, site or recurring problems; wiki facts take precedence over the model's general knowledge and the page used is cited.
- Hard consent gate on writes:
wiki_appendalways shows a confirmation dialog with the exact text about to be saved — field testing proved that small local models skip prompt-level consent instructions and even invent details (dates) that were never stated. Declining feeds an explicit "user declined, do not retry" back to the model, and the tool description forbids adding details the user did not state. - The plugins never touch consolidated
wiki/pages: the AI Weather plugin appends daily sky digests to the same shared wiki, and the separate nina.autopilot ingest agent (--wiki-ingest/--wiki-lint) consolidates raw notes into proper pages.
Options panel
- New "Disable model thinking" toggle in the Ollama section (on by default) — makes the 2.5.2.0 behavior user-controllable; changing it re-initializes the provider immediately.
- Checkboxes (Enable MCP, orchestrator panel, the new thinking toggle) and every button row (Refresh, Test Connection, Get Advanced API Plugin / MCP GitHub Repo, Validate / Reset, Add to Config, Documentation / Example Server) are now consistently left-aligned instead of centered/stretched.
Full changelog: https://github.com/michelebergo/nina.plugin.aiassistant/blob/main/CHANGELOG.md
Release 2.5.2.0
Automatically generated manifest for release 2.5.2.0.
What's in this release:
- Ollama thinking-capable models (Gemma 4, Qwen 3.x, DeepSeek) were slow or returned empty replies (fixes #8): Ollama enables a "thinking" phase by default on newer models — replies took several times longer (77.6s vs 14.2s field-measured on the same request), and on some runs the actual answer lands in a separate
thinkingfield whilecontentcomes back empty. Requests now sendthink: falseby default on both the chat and tool-calling paths, and the parser recovers answers from thethinkingfield and strips inline<think>blocks.
Full changelog: https://github.com/michelebergo/nina.plugin.aiassistant/blob/main/CHANGELOG.md
Release 2.5.1.0
Release 2.5.1.0 - Gemini test/defaults fixed (gemini-flash-latest ali…