Skip to content

Added RAG implementation, setup wizard and other fixes - #65

Open
lsoft wants to merge 23 commits into
mainfrom
fix/mcp-proxy-restart-and-concurrency
Open

Added RAG implementation, setup wizard and other fixes#65
lsoft wants to merge 23 commits into
mainfrom
fix/mcp-proxy-restart-and-concurrency

Conversation

@lsoft

@lsoft lsoft commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Five things which grew out of one another: the MCP proxy was fixed first, then the natural language
search was taught to use an embedding index, the search machinery which came out of that turned out
to be the right home for a grep tool as well, and a setup wizard was added so a new install has a
guided way to replace the configuration this repository ships with.

Version bumped to 4.3.0. The index files of TestSubject are regenerated in the new format.

RAG for the natural language search, and a window to calibrate it

The search used to hand every text file of the scope to the model, one context window at a time.
With Use RAG checked it asks the embedding index which files are worth reading and gives the model
those only.

  • Search\FreeAIr.Search.csproj (netstandard2.0) is extracted out of the VSIX: the index format, the
    vector codec, the outline tree and the ranking know nothing about the IDE, and the VSIX assembly
    cannot be loaded by a test runner. That is what makes any of this testable at all —
    Search.Tests\ is new too.
  • New on-disk format: quantized vectors written one per line, no embedding for an outline which is
    nothing but the name of the member it describes, and an order which does not depend on the machine
    which wrote the file. Eighteen times less disk space on the sample solution, and a merge instead of
    a conflict when two branches rebuild the index. Not backward compatible — an index built by
    4.2.11 or earlier has to be rebuilt.
  • The index remembers which model built it by storing the vectors of a few fixed sentences, so a
    search with another model is refused instead of returning noise. The vector length alone did not
    catch this, since unrelated models often share it.
  • RagMinScore is gone. Every build measures what a query with no answer scores on this model and
    this solution, and Sensitivity says how far above that measured noise a file has to stand — one
    number which keeps its meaning when the embedding model changes.
  • Extensions / FreeAIr / Open RAG search calibration window... asks the index the questions the
    user would ask the search, shows what the threshold lets through and what it cuts, and saves the
    result without rebuilding the vectors: a threshold is fixed in a minute instead of in an hour of
    embedding.
  • The search is cancellable at every step, shows its shortlist before the first answer arrives, and
    writes what it is doing into a FreeAIr natural language search pane of the Output window instead
    of giving up in silence in six different places.

A grep tool for the built-in Visual Studio MCP server

Finding where a text occurs used to mean handing whole files to the model one by one.
VisualStudio.SearchFileContent answers that question directly: the matching lines, each with its
file and line number.

Nothing is installed and no process is started — the matching is Search\Grep\. Shipping a
grep.exe inside the VSIX would have bought speed nobody asked for, at the price of a third party
binary, its licence and the antivirus reports about it.

Parameter
pattern the only required one; a literal by default, a .NET regular expression when is_regular_expression is set
case_sensitive, whole_word the usual two
invert_match the lines which do not match, the way grep -v does
search_scope the files of the projects (default), or every file in the solution folder
subfolder, file_mask *.cs;*.xaml; a mask which starts with ! subtracts, so *.cs;!*.Designer.cs keeps generated code from eating the budget
context_line_count, max_result_count 0–5 lines around a match; 100 matches by default, 500 at most
  • The answer says whether the cap was reached. A truncated list which does not admit to being one is
    read by the model as the whole truth.
  • Running inside devenv is what a grep.exe could not have done: a document which is open and not
    saved yet is searched as the user sees it. Those buffers are collected on the main thread and the
    scan itself runs off it, so a solution of thousands of files does not freeze the IDE.
  • Build output, version control and package folders are skipped, files which are not text are
    detected by extension and by content, and the regular expression — written by a model — is given a
    five second timeout, so one pathological file is reported instead of hanging the IDE.

MCP proxy lifecycle, options and concurrency

  • A server which was reconfigured no longer gets a second wrapper, so its tools stopped being offered
    to the model twice, three times and so on.
  • The JSON-RPC channel is re-attached to the streams of a restarted proxy, which used to leave every
    MCP call after the first crash lost, and the configuration is pushed into the fresh process again.
    A failed start is retried instead of ending the monitoring for the session.
  • Proxy.zip decides "already unpacked" by a marker written after the last entry, so an interrupted
    unpacking is repaired instead of being trusted.
  • Options: a deserialization which returned null against its own contract, a serialization which
    threw when no solution was open, and an MCP server installation which added a duplicate entry.
  • Concurrency: ChatContainer handed out its live list of chats and read it without the lock,
    LLMReader could hand a cancelled token source to a read started right after a stop, and
    FileCacheEntry updated its value across an await unsynchronized.
  • UI: the buttons inserted into the Git Changes pane and the Find in Files dialog are restored
    after Visual Studio rebuilds them, and windows are no longer subscribed to Closed on every
    Loaded.

A first-run setup wizard

A new install starts with the configuration this repository ships with — placeholder tokens, the
author's own endpoints — and the only way to replace it was to reverse-engineer the settings file or
to find the control center's per-entity editors one at a time. The wizard walks through agents, MCP
servers, actions and the remaining settings, says what each step is for, and writes nothing until
Finish. An info bar offers it the first time FreeAIr runs (alongside the release notes, once), and
it stays available from Extensions / FreeAIr / Open setup wizard....

  • SetupWizard\FreeAIr.SetupWizard.csproj (netstandard2.0) holds what needs neither Visual Studio
    nor WPF: step navigation and skipping, the agent-field and action-binding validators, the known
    endpoint and known MCP server catalogs. SetupWizard.Tests\ covers it with 45 tests. Same split,
    and the same reason, as FreeAIr.Search.
  • That project carries no resources, so its validators report enum codes and the view model renders
    them into localized sentences. The window itself is fully localized — 79 new keys in the en,
    ru and zh-Hans resx — and takes its colours from the Visual Studio theme rather than from
    literals, so its text is readable under a dark theme too.
  • On a first run the shipped sample agents are wiped and the user is guided through creating one
    of their own field by field, each field with its own explanation, plus a test connection check of
    the endpoint (the same GetModelsAsync call the model picker makes) and a choice between pasting a
    token and naming an environment variable which holds it. A later run gets the ordinary multi-agent
    list editor instead.
  • The actions page explains what an action is, gives examples, and warns in red about every
    action naming an agent which does not exist — which is what renaming or deleting an agent silently
    produces. A Use default values button restores the shipped prompt library bound to the first
    agent.
  • The run whole line completion as you type switch sits on that same page, because it is what makes
    the whole line completion action live or dormant: while it is off that action is neither bound by
    the defaults button nor reported as a problem, and ticking it does both.
  • The Microsoft Learn documentation MCP server is one checkbox on the MCP servers page — a public
    HTTP endpoint, so nothing is downloaded and no token is needed. Its name and endpoint moved into
    KnownMcpServerCatalog, which the control center's install command reads too, so the two cannot
    drift apart and a server installed by one is recognized by the other.
  • The GitHub MCP server is opt-in: nothing asks for a GitHub token until the box is ticked.
  • Nothing here may throw into WPF's dispatcher — an unhandled exception from a modal dialog inside
    devenv ends Visual Studio rather than the dialog — so every command body, the window loading, the
    info bar and the package hook each catch, log to the activity log, and report.
  • Existing editors are reused rather than reimplemented: the MCP servers and actions steps open
    McpServerConfigureWindow / ActionConfigureWindow against a clone, so a cancelled sub-dialog
    leaves the wizard untouched. DirectOrEnvStringHelper moved into the new project instead of being
    copied into it, and the shipped defaults stayed the single source they already were.

Separately, whole line completion no longer opens an error dialog on every pause in typing when its
action names no existing agent. That is how the shipped agent_name_must_be_set placeholder used to
interrupt a brand new install, the wizard included. The complaint goes to the activity log now, and
is shown as a dialog only when a suggestion was asked for explicitly with Alt+A.

Documentation

ARCHITECTURE.md describes the projects, the flow of a chat and the MCP, search and setup wizard
subsystems; CLAUDE.md holds what an automated agent needs to build this repository — full MSBuild
rather than the .NET SDK, why dotnet build breaks the next build, how to run the tests, and the
fact that a new file in the legacy-format FreeAIr.csproj has to be added to it by hand or it is
silently not compiled.

Checks

FreeAIr.sln builds with 0 errors in Release (the ~800 warnings are pre-existing), and
run-tests.bat is green: 112 passing in FreeAIr.Search.Tests with 6 integration tests skipped
without an embedding server, and 45 passing in FreeAIr.SetupWizard.Tests.

🤖 Generated with Claude Code

lsoft and others added 4 commits August 2, 2026 11:54
…efects.

MCP proxy:
- ProcessMcpServerProxyAsync no longer appends a second wrapper for a server
  which is already running, so the tools of every reconfigured server stopped
  being offered to the model twice, three times and so on. The wrapper of a
  server which failed to start is dropped as well - GetTools enumerates the
  wrappers, so removing its tools from the container alone was not enough.
- The JSON-RPC channel is re-attached to the streams of the restarted proxy.
  ProcessMonitor did restart the process, but the channel stayed bound to the
  streams of the dead one, so every MCP call after the first crash was lost.
  A freshly started proxy hosts no MCP servers, so the configuration is pushed
  into it again. Started/ProxyInterface now tell whether the channel is alive.
- A failed start no longer ends the monitoring for the rest of the session: it
  is retried with a pause, and given up only after several failures in a row.
- Proxy.zip: "already unpacked" is decided by a marker file written after the
  last entry. The folder used to be created before the first entry, so an
  interrupted unpacking left a truncated folder which was never repaired.

Options:
- DeserializeAsync returned null when a place was asked for explicitly and
  nothing was there, contrary to its own contract; callers dereference it.
- SerializeAsync into a solution-related file with no solution opened reports
  what has happened instead of throwing ArgumentNullException from FileInfo.
- Installing the MSDN MCP server overwrites the entry instead of Add-ing it:
  the name could be taken already, and CanExecute only looks at the endpoint.

Concurrency:
- ChatContainer handed out the live list of chats and read it without the lock,
  while chats are added from the UI thread and their statuses change on the
  threads which stream the answers. Events are no longer raised under the lock.
- LLMReader could hand a cancelled (and then disposed) token source to a read
  started right after a stop, and the finishing read could null the _task of a
  newer one.
- FileCacheEntry updated its value and its signature around an await without
  any synchronization, and dereferenced a null the converter is allowed to
  return.

UI:
- The buttons inserted into the Git Changes pane and into the "Find in Files"
  dialog are restored after Visual Studio rebuilds them. The scan stopped after
  the first insertion, so reopening the dialog left it without our controls.
- Windows are no longer subscribed to Closed on every Loaded.
- The FreeAIrPackage summary stood after the attributes: CS1587, and it never
  made it into the documentation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Documents that the solution requires full MSBuild from the Visual Studio
installation, since the projects are legacy-format VSIX/.NET Framework 4.8
and the VSSDK targets are unavailable to the .NET SDK.

Also records two non-obvious traps found while building:

- "dotnet build" not only fails, it rewrites obj/project.assets.json with
  .NET SDK semantics and breaks the next MSBuild build with a spurious
  "doesn't list win as a RuntimeIdentifier" error. Recovery is to re-run
  the MSBuild restore.
- vswhere.exe returns an empty list here, so toolchain discovery through it
  silently finds nothing and the MSBuild path must be given explicitly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The search used to hand every text file of the scope to the model, one context
window at a time. With `Use RAG` checked it now asks the embedding index which
files are worth reading and gives the model those only.

Index:

- Extracted `Rag\FreeAIr.Rag.csproj` (netstandard2.0) out of the VSIX: the
  index format, the vector codec, the outline tree and the ranking know nothing
  about the IDE, and the VSIX assembly cannot be loaded by a test runner. That
  is what makes any of this testable at all.
- New on-disk format. Vectors are quantized and written one per line, and an
  outline which is nothing but the name of the member it describes is not
  embedded at all - eighteen times less disk space on the sample solution. The
  order does not depend on the machine which built the file, so two people
  rebuilding the index in two branches get a merge instead of a conflict.
- One file less: the tree of the outlines is derived from the outlines instead
  of being stored. The format is not backward compatible; an index built by
  4.2.11 or earlier has to be rebuilt.
- The index remembers which model built it, by storing the vectors of a few
  fixed sentences. A search with another model is refused instead of returning
  noise - the vector length alone did not catch it, since unrelated models
  often share it. The name the server reports for itself is recorded too, which
  is the only name that changes when a local server is given another model.
- `RagMinScore` is gone. Every build now measures what a query with no answer
  scores on this model and this solution, and `Sensitivity` says how far above
  that measured noise a file has to stand - one value which keeps its meaning
  when the embedding model changes. `RagTopOutlineCount` and `RagMaxFileCount`
  moved into a `Rag` node of their own.
- `EmbeddingIndexContainer` is shared by the search and the GetAllSolutionFiles
  MCP tool, which used to read the whole index on every call.

Calibration:

- `Extensions / FreeAIr / Open RAG search calibration window...` asks the index
  the questions the user would ask the search, shows what the threshold lets
  through and what it cuts, and saves the questions into the settings and the
  numbers into the index - without rebuilding the vectors, so a threshold is
  fixed in a minute instead of in an hour of embedding.
- Queries whose answer is known are kept in the settings as well: the threshold
  is never allowed to climb up to them, and a query which fails to find its own
  file is reported at the end of the build, because that means the model does
  not understand this codebase.

Search:

- Every step is cancellable, including the reading of the index.
- The shortlist is shown before the first answer arrives: that is the only
  moment where the user can tell the search is looking in the wrong place.
- The results window names the agents behind the answers - the one which was
  asked, and, for a RAG search, the one which vectorized the query. The second
  one is normally chosen from the index rather than by the user.
- The `Confidence` column reads `High (85)` instead of `85`. The number is a
  guess of the model, not a measurement.

Fixes:

- An agent without a token was invisible to everything which looks an agent up
  by name. An embedding server run locally wants no token, so the agent which
  had built the index was never found and a cloud chat agent was silently used
  to vectorize the query - which answers a request for embeddings with 400.
- An embedding server which refuses a request is now quoted. `HTTP 400` alone
  says nothing about which model or which parameter it did not like, and the
  server had already explained it in an answer that was being discarded.
- The results window failed to open at all: its progress bar was bound two way
  onto a read only property, which throws while the window is being built.
- The natural language search gave up in silence in six places. An empty file
  mask now means every file, as it does in `Find in Files`, instead of killing
  the search with an exception nobody sees; the other five say why they stop.
  Every step also writes itself into a `FreeAIr natural language search` pane
  of the Output window.
- `Edit actions`: clicking an action did nothing. `SelectedAction` was writing
  into the backing field of the property while the rest of the window kept
  reading a separate field, which therefore stayed null - the editing panel was
  hidden and every command disabled.

Tests and docs:

- `Rag.Tests` (net8.0, xunit) covers the index format, the vector codec, the
  outline tree, the ranking and the calibration. `run-tests.bat` builds with
  MSBuild first, because letting the .NET SDK restore breaks the VSIX build.
  `run-integration-tests.bat` runs the tests which need a real server.
- The calibration and NLO windows describe themselves in a block at the top.
- README, ARCHITECTURE and the release notes follow.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
lsoft and others added 5 commits August 3, 2026 11:18
Finding where a text occurs used to mean handing whole files to the model one
by one. `VisualStudio.SearchFileContent` answers that question directly: the
matching lines, each with its file and line number.

Nothing is installed and no process is started - the matching is
`Rag\Grep\GrepSearch.cs`. Shipping a `grep.exe` inside the VSIX would have
bought speed nobody asked for, at the price of a third party binary, its
licence and the antivirus reports about it.

- Literal by default and a .NET regular expression on request, both through the
  same code path - the literal one is escaped. `case_sensitive` and
  `whole_word` are the other two switches, and `invert_match` reports the lines
  which do not match, the way `grep -v` does.
- `search_scope` chooses between the files of the projects (the default) and
  every file in the solution folder. The walk skips `bin`, `obj`, `.git`,
  `node_modules` and the like either way, so a search does not answer with
  build output.
- `file_mask` is `*.cs;*.xaml`, and a mask which starts with `!` subtracts:
  `*.cs;!*.Designer.cs` is what keeps generated code from eating the budget.
- The answer is capped - 100 matching lines by default, 500 at most - and says
  whether the cap was reached. A truncated list which does not admit to being
  one is read by the model as the whole truth.
- Running inside devenv is what a `grep.exe` could not have done: a document
  which is open and not saved yet is searched as the user sees it rather than
  as it is on the disk. Those buffers are collected on the main thread and the
  scan itself runs off it, so a solution of thousands of files does not freeze
  the IDE.
- The pattern is written by a model, so the regular expression is given a five
  second timeout: the file which makes it misbehave is reported and the rest of
  the search survives.

The matching, the masks and the decoding of a file into lines live in
`FreeAIr.Rag`, which a test runner can load, and are covered by
`Rag.Tests\GrepFacts.cs`. The tool itself is the Visual Studio half of it.

CLAUDE.md gets a warning as well: a new file in the legacy-format
`FreeAIr.csproj` has to be added to it by hand. This tool was missing from the
built assembly for exactly that reason, with the build still reporting no
errors at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4.2.12 was never released: the version was raised to it and then to 4.3.0
a couple of hours later, so the RAG search - the `Use RAG` checkbox, the
new index format, the calibration window - ships in 4.3.0 together with
the grep MCP tool.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
4.2.12 is a released version and keeps its section, but it shipped the fix
for issue #61 only: the RAG search - the `Use RAG` checkbox, the new index
format, the Sensitivity setting and the calibration window - is part of
4.3.0, and so are the MCP proxy, options and concurrency fixes which had
no release note at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The C# scanner fed the embedding index only the bare text runs of a
<summary>, so everything inside <see cref>, <c>, <list> and <paramref>
was dropped on the way in: "Reads the <see cref="EmbeddingIndex"/> from
disk" reached the index as "Reads the from disk". Bullet lists vanished
whole. It also never visited enums, delegates, events or indexers, so a
comment on any of them was indexed nowhere.

CleanCommentText now walks the nested markup and keeps the identifiers
out of cref and name attributes, and the tree builder emits nodes for
every declaration a summary can be written on. Node ids of existing
members are unchanged; enums and the rest are new nodes, so the index
has to be rebuilt to pick them up.

Overloads still collapse onto one Target of Type.Method and therefore
one id, so only one of their summaries survives. Left alone here: fixing
it changes the ids of every overloaded member and the Type.Member
convention OutlineTreeAssembler splits on.

With that fixed, commented the core - Chat, BLogic and the support
actions - aiming at what the index actually stores rather than at
formal doc comments. Nodes carrying a real outline went from 918 to
1030 of 4299; Chat 43%, BLogic 49%.

CLAUDE.md gains a section on what the scanner reads and how to write
for it, since none of this is guessable from the code.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@lsoft
lsoft force-pushed the fix/mcp-proxy-restart-and-concurrency branch from bafbdbc to eee7396 Compare August 3, 2026 10:53
lsoft and others added 6 commits August 3, 2026 16:05
Continues the pass started in the previous commit: the parts of the core
the scanner still saw as bare identifiers, and which were therefore absent
from the embedding index entirely.

Covered here:

- Chat and ChatContainer - the ownership and the lifetime rules, why the
  context is injected right before the last prompt, why archiving is what
  brings the token cost of a long dialogue back down.
- TextDescriptor - the two ways an answer is written back, and why the
  selected variant goes through the text buffer rather than the file.
- TypeReferenceWalker - what each override harvests a type from, and why
  types from referenced assemblies are dropped.
- SupportContext - what every prompt anchor stands for and which scope
  supplies it.
- FreeAIrOptions, AgentJson, AgentCollectionJson, McpServersJson - where the
  settings live, how a token is resolved out of an environment variable,
  and what the shipped system prompts are for.

Nodes carrying a real outline: 1030 -> 1181 of 4299. Chat 43% -> 69%,
Options2 27% -> 70%.

The overload collision is still there: two methods sharing Type.Method share
one node id, so only one summary reaches the index. WithContextItemAsync says
so in its own summary; fixing it would change the id of every overloaded
member.

Release builds with 0 errors, Rag tests 112 passed / 6 skipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Covered here:

- CallAwaiter - the callback-to-awaitable adapter behind recording and
  similar one-shot async operations, and why the finalizer fires as a
  last-resort guard.
- RecorderTranscriberPostProcessor - the record/transcribe/post-process
  loop, its status events, and how a misconfigured post-process action
  falls back to the raw transcription.
- UnsortedJson - the settings that never got a dedicated node: output
  length, answer culture, GitHub token resolution, whole line completion.
- RagJson - summaries on the properties and the calibration probe types
  that the Description attributes alone do not reach the outline index.

Nodes carrying a real outline: 1181 -> 1214 of 4299.

Release builds with 0 errors, Rag tests 112 passed / 6 skipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`FreeAIr.Rag` was never really "the RAG project" - its csproj comment always
said what it is: the half of search that does not need Visual Studio and can
therefore be exercised by an ordinary test runner. The natural language
search (index, vector codec, outline tree, ranking) and the Grep text
matcher behind the SearchFileContent MCP tool live there for that one
reason, testability, not because Grep has anything to do with retrieval
augmented generation. The old name just happened to describe the bigger
half and mislead about the rest.

Renamed via `git mv`, tracked as renames:

- Rag/ -> Search/, Rag.Tests/ -> Search.Tests/
- FreeAIr.Rag.csproj -> FreeAIr.Search.csproj (AssemblyName, RootNamespace,
  InternalsVisibleTo), same for the Tests project
- every test file's `namespace FreeAIr.Rag.Tests` -> `FreeAIr.Search.Tests`
- FreeAIr.sln project entries, FreeAIr.csproj's ProjectReference, run-tests.bat
- CLAUDE.md, ARCHITECTURE.md, and the two doc comments in FreeAIr\Embedding
  that named the assembly in prose

Domain types genuinely about the RAG feature keep their names as they should
- RagShortlist, RagCalibration, RagJson, RagCalibrationViewModel - only the
  project/assembly identity moved.

Release builds with 0 errors; Rag.Tests -> FreeAIr.Search.Tests still
112 passed / 6 skipped under the new name.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Four of the built-in Visual Studio tools take no arguments and declared an
empty `{}` schema. LM Studio validates `function.parameters` and answers the
whole completion request with 400, so one such tool took every other tool and
the conversation with it. Tool schemas are now normalized on their way to the
model rather than at the four declarations only: the schemas of third party MCP
servers reach us unseen and may say the very same thing.

The natural language search and the outline generation hit the same status from
the other end, by asking for the `json_object` response format which LM Studio
does not implement. They ask for the json in the prompt, as they already did,
and the answer passes the cleanup which strips fences and reasoning blocks
before it is parsed.

Tool calls are also reassembled from the whole stream instead of its first
chunk. The arguments arrive as deltas across the following chunks, and reading
only the first one ran the tool with no arguments and sent a half-read call
back to the server, which replied 500.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
lsoft and others added 5 commits August 5, 2026 10:26
Adds <summary> XML doc comments across the MCP proxy protocol (Dto/*, the
Proxy process's Server/* and BLogic/Api.cs) and the VSIX-side MCP tool
implementations (ServerProxy/*), so this code is findable through the
natural-language search instead of being invisible to it. MCP coverage in
the outline index goes from 2% to 31%.
…ch coverage.

Adds XML doc summaries to the ANTLR listener, the block/part model,
the table/xml/image/url renderers and the parser entry points
(CachedMarkdownParser/DirectMarkdownParser), following the same
NLO-outline convention used for MCP. No logic changes.
…age.

Covers the cross-process CodeLens flow (Shared DTOs/contracts, the
out-of-process data point in CodeLens/, the Visual Studio-side listener and
connection handler in FreeAIr/CodeLens/, and the details-pane view model)
plus the WpfHelpers MVVM/command/collection utilities.
…elpers surface for NLO/RAG search coverage.

Raises overall NLO/RAG comment coverage from 36% to 95% (FreeAIr core 33%->95%, MCP 31%->98%, MarkdownParser 50%->96%, CodeLens 56%->91%, WpfHelpers 77%->96%).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…when it is not configured.

A new install of FreeAIr starts with the author's own debug configuration - placeholder tokens,
personal endpoints - and no guided way to replace it. The wizard walks through agents, MCP servers,
actions and the remaining settings, explaining each step, and writes nothing until the last page.
It is offered by an info bar the first time FreeAIr runs and stays available from
Extensions > FreeAIr > Open setup wizard...

The logic that needs neither Visual Studio nor WPF - step navigation, the agent-field and
action-binding validators, the endpoint and MCP server catalogs - lives in the new netstandard2.0
SetupWizard project so an ordinary test runner can reach it (SetupWizard.Tests, 45 tests), the same
split as FreeAIr.Search. It carries no resources, so its validators report enum codes which the view
model renders into the localized sentences; the window itself is fully localized like the rest of
the product.

Notable behaviour:

- On a first run the shipped sample agents are wiped and the user is guided through creating one of
  their own field by field, with an endpoint reachability check and a choice between a literal token
  and an environment variable holding it. A later run gets the ordinary multi-agent list editor.
- The actions page explains what an action is, warns in red about any action naming an agent which
  does not exist, and can restore the shipped prompt library bound to the first agent.
- Whole line completion is switched on and off on that same page, because it is what makes its
  action live or dormant: while it is off the action is neither bound by the defaults button nor
  reported as a problem.
- The Microsoft Learn documentation MCP server is one checkbox on the MCP servers page. Its name and
  endpoint move into KnownMcpServerCatalog, which the control center's install command now reads
  too, so the two cannot drift apart.
- The GitHub MCP server is opt-in; nothing asks for a GitHub token until the box is ticked.
- Nothing in the wizard may throw into WPF's dispatcher - an unhandled exception in a modal dialog
  inside devenv ends Visual Studio rather than the dialog - so every command body, the window
  loading, the info bar and the package hook each catch, log and report.

Separately, whole line completion no longer opens an error dialog on every pause in typing when its
action names no existing agent. That is how the shipped agent_name_must_be_set placeholder used to
interrupt a brand new install, the setup wizard included. The complaint goes to the activity log,
and is shown as a dialog only when a suggestion was asked for explicitly with the shortcut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@lsoft lsoft changed the title Added RAG implementation Added RAG implementation, setup wizard and other fixes Aug 5, 2026
lsoft and others added 3 commits August 6, 2026 20:40
Скан индекса и так считает скор каждой записи, поэтому фоновый уровень
конкретного запроса достаётся бесплатно: медиана и нижний квартиль всего
ранжира дают порог median + k*sigma, где k читается из той же Sensitivity.

Это работает на индексе, который никогда не калибровали, и снимает то, чего
единственное число калибровки не видит: общий короткий запрос близок ко всему
корпусу, узкий - ни к чему. Файл обязан пройти оба порога.

Разброс берётся по нижней половине распределения - верхняя это и есть ответы,
и порог рос бы каждый раз, когда поиск срабатывает. На индексе меньше 256
записей порога отсюда нет вовсе: квартили десятка чисел не квартили.

Разбор калибровки и ещё четыре способа сделать её автоматической - в
devdocs/RAG_AUTO_CALIBRATION.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant