NETReporter.Client 3.4.0

NETReporter.Client

Tenký klient pro ReportServer: stejné rozhraní jako knihovna NETReporter, ale report se vykreslí na serveru. Aplikace nemusí nést QuestPDF, Roslyn, OxyPlot ani ZXing; přihlašuje se API tokenem, který si vygenerujete v UI ReportServeru.

Klient implementuje IReportRenderer a ITemplateTools z balíčku NETReporter.Abstractions, takže mezi lokálním a vzdáleným renderem přepíná jen registrace v DI. Kód, který renderuje, se nemění.

Instalace

dotnet nuget add source https://nuget.advisor-soft.com/v3/index.json --name AdvisorSoft
dotnet add package NETReporter.Client

Požadavky: .NET 10. Balíčky NETReporter, NETReporter.Abstractions a NETReporter.Client se vydávají společně se stejnou verzí.

API token

  1. Přihlaste se do UI ReportServeru a otevřete stránku API tokeny.
  2. Zadejte název (a případně dobu platnosti) a token vytvořte. Otevřený text se ukáže jen jednou, server si pamatuje jen hash; uložte ho do tajných hodnot (proměnná prostředí, user secrets, trezor), ne do repozitáře.
  3. Token má stejná práva jako jeho vlastník. Odvolat ho může vlastník i správce; deaktivace vlastníka ho vyřadí hned.

Rychlý start s DI

using Microsoft.Extensions.DependencyInjection;
using NetReporter;

services.AddNetReporterClient(options =>
{
    options.BaseAddress = new Uri("https://reports.example.com/api");   // adresa API včetně předpony cesty
    options.ApiToken = configuration["NetReporter:ApiToken"];           // nrp_…
});

// kdekoli v aplikaci
public sealed class InvoiceService(IReportRenderer renderer)
{
    public async Task<byte[]> CreatePdfAsync(Stream template, Stream data)
    {
        await using var pdf = await renderer.RenderAsync(template, data);
        using var buffer = new MemoryStream();
        await pdf.CopyToAsync(buffer);
        return buffer.ToArray();
    }
}

Nastavení jde číst z konfigurace: services.AddNetReporterClient(configuration) čte sekci NetReporterClient s klíči BaseAddress, ApiToken a Timeout. Chybějící adresa nebo token zastaví aplikaci při startu srozumitelnou chybou.

Bez DI

using NetReporter.Client;

using var http = NetReporterClient.CreateHttpClient(new NetReporterClientOptions
{
    BaseAddress = new Uri("https://reports.example.com/api"),
    ApiToken = Environment.GetEnvironmentVariable("NETREPORTER_API_TOKEN")
});

IReportRenderer renderer = new ReportServerRenderer(http);
ITemplateTools tools = new ReportServerTemplateTools(http);

Co klient umí

  • Render libovolné šablony (ad-hoc) do všech formátů: PDF, HTML, JSON, SVG, WebP, PNG, JPEG, i po stránkách (RenderSvgPagesAsync, RenderWebpPagesAsync, …) a se všemi volbami RenderOptions (PDF/A, přílohy, šifrování, vodoznak, rozlišení…).
  • Diagnostiky bindingů přes RenderOptions.OnBindingDiagnostics a pozorovatele pipeline.
  • Nástroje nad šablonou (ITemplateTools): validace šablony a dat, datový kontrakt a ukázková data.
  • Mimo rozsah: správa uložených šablon, render podle uložené šablony a historie jobů (ty zůstávají v UI a REST API).

Čím se vzdálený render liší od lokálního

  • Soubory z disku se na serveru nenačítají: obrázky, SVG ani podklady PDF z cesty k souboru nefungují (použijte data URI nebo adresu http/https).
  • Server omezuje počet stránek, rozlišení obrazů a velikost příloh; diagnostik bindingů vrací nejvýše 50 různých.
  • RenderOptions.Icons se nepoužije: server vykresluje ikony vlastním katalogem.
  • Pozorovatel pipeline dostane zjednodušené události (parsování proběhlo na serveru).

Chyby

Situace Výjimka
Chyba v šabloně ReportServerException (kód TEMPLATE_VALIDATION_FAILED, Diagnostics s JSON cestami)
Vadné volby ArgumentException (ParamName == "options"), u lokálních kontrol bez volání serveru
Překročený limit stránek RenderPageLimitExceededException
Zrušení volajícím OperationCanceledException
Neplatný, odvolaný nebo prošlý token ReportServerException (AUTH_UNAUTHORIZED)
Server nedostupný nebo překročený Timeout ReportServerException (REPORTSERVER_UNAVAILABLE nebo REPORTSERVER_TIMEOUT)

ReportServerException dědí z InvalidOperationException, takže ji zachytí i kód napsaný pro lokální render. Seznam změn je v souboru CHANGELOG.md v balíčku.

No packages depend on NETReporter.Client.

- Template editor (AI assistant): prompt variants. Each model (and each operation binding) has a prompt variant, *heavy* (the full rules, the default) or *light* (`system-rules.light.md`, `template-cheatsheet.light.md`, `document-rules.light.md`: 13 to 22 % shorter, numbered imperative rules, a step-by-step procedure and, for the task template from a document, one example of a labelled grid), independent of the schema profile `Full`/`Compact`. The safety rules are in both, a prompt is byte-stable per variant (prompt cache), and a resource without a light variant (review, translation...) is shared. Measured on the 17 scenarios of `tools/assistant-eval` (new switch `--variant heavy|light`): a local `kat-coder` (Ollama, no reasoning, 2 runs each) 29/34 heavy against 31/34 light with 10.4 s instead of 18.8 s per run, DeepSeek 17/17 for both. The *Ollama* template of the model page defaults to light. - Template editor (AI assistant): the models, their parameters and keys are administered **at runtime** by the owner on the new page *Modely asistenta* (`/admin/assistant-models`; the gear button of the editor bar and the item in the user menu, shown to owners only). A model is OpenAI-compatible (`openai`, Ollama or vLLM through `/v1`) or Anthropic-compatible (`anthropic`, for example DeepSeek at `https://api.deepseek.com/anthropic`) and has the endpoint, the model name, the key (write-only, shown as `…a1b2`), the context budget, tool calling, image input, the prompt variant, the data level cap, the concurrency and runs per hour, the prices and a cache breakpoint switch. Two default slots (*simple*: review, expression, translation, sample data, data mapping, help; *complex*: edit, fix, template from a document) bind the operations to models and each of the nine operations can override the model, the reasoning, the round count, the output caps and the timeout, so a document conversion can run on a hosted DeepSeek while the small operations stay on a local Ollama. The page validates with the same rules as the server, tests a connection and the context length (the long probe asks before it spends money on a hosted model), imports the model from the environment variables and warns when a binding would leave an operation unusable. A change applies to the next run on this pod at once and on the other pods within 30 seconds; runs in flight finish with their snapshot. - **Behavior change** Template editor (AI assistant): the environment variables `EDITOR_AI_LOCAL_*`, `EDITOR_AI_MAX_ITERATIONS`, `EDITOR_AI_DOCUMENT_MAX_ITERATIONS`, `EDITOR_AI_RUN_TIMEOUT_SECONDS` are now only a **seed**: while the owner has saved nothing (the API returns revision 0, or the API is an older version without the endpoint), they build one model `local` bound to every operation, exactly as before; a saved configuration, even with no model, takes over completely. `EDITOR_AI_ENABLED` is now tri-state: not set means *on when the catalog has a usable model*, `false` switches the assistant off and hides the page (it had to be `true` before). `EDITOR_AI_ANTHROPIC_ENABLED`, `EDITOR_AI_USER_KEY_DATA_LEVEL`, `EDITOR_AI_COST_WARNING_USD` and `Assistant:Providers:*` are removed and ignored. The startup probe of the local model is gone (the editor has no service identity to read the configuration at startup); the same check is the *Otestovat kontext* button of the page. The deploy samples (`deploy/k8s/03-configmap.yaml`, `deploy/compose/.env.sample`, `docker-compose.sample.yml`) say so. - **Behavior change** Template editor (AI assistant): **the keys of the users and the model selector are removed.** Every model is managed and paid by the operator, so the panel no longer offers a model, an API key, the Anthropic models, the OpenAI-compatible presets, the per-run consent to sending data or the cost warning; each tab shows the line *Model: … (u provozovatele / hostovaná služba)* and where the template goes. The page *Nastavení* and the user key storage UI are deleted. The assistant is available to users with the role **Asistent**, **Admin** or **Owner** (an editor without the role who used their own key loses the assistant); an owner must also be Editor or Admin to reach the editor, like in the ReportServer UI. Before updating, an owner should create the models on the new page; the keys stored by users are not used any more. - ReportServer (migration `AddAssistantModelConfig`): the tables `AssistantModelConfigs` (one row: the revision as a concurrency token and the `jsonb` document of the models and bindings without secrets) and `AssistantModelSecrets` (the key encrypted by the editor with Data Protection bound to the model id, and its hint), the endpoints `GET/PUT /owner/assistant/models` (policy `InteractiveOwner`; `ETag` `"r{revision}"`, `If-Match` required: `428` without it, `412` with the current revision on a conflict, `400 ASSISTANT_CONFIG_INVALID` with the list of problems) and `GET /assistant/runtime-config` (the new policy `AssistantRuntime`: role Assistant, Admin or Owner, JWT only, and the claim `azp` = `template-editor`, so a JWT from a direct API login never receives the encrypted keys; `Cache-Control: no-store`, `304`). The validation `AssistantConfigRules` is shared with the editor page and refuses addresses with credentials and link-local or cloud metadata addresses (SSRF). `GET/PUT /me/assistant-settings` and `/me/assistant-keys` with their tables stay for one release (older editor pods during a rolling update) and will be removed with the stored user keys. The usage ledger records every managed model as `ProviderKind = local` with the model id as `ProviderId`, and the operation *data mapping* as `data`. - Template editor (AI assistant) fix: the task *template from a document* ended with *Vyčerpán počet kol* or lost the labels of a form. Measured against DeepSeek with a one-page PDF form: without reasoning the model spent 11 to 14 rounds on `get_node_schema` calls it did not need and bound the static labels to invented data fields of a `Table`; with low reasoning it finishes in 4 rounds and keeps the labels. Changes: the task now defaults to **low reasoning** (the other operations stay without reasoning) and to the output caps 32 000 / 48 000 tokens with reasoning per response and 60 000 / 120 000 per run (high reasoning exhausted 32 000); the `Full` prompt says that the schema digest is complete (`get_node_schema` is only for `page` and `watermark`); the rules for a document say that a static grid of labels and values is `Row` + `Box` + `Text` and that `Table` is only for rows from data; the check *server truncates the context* no longer counts the model's reasoning (DeepSeek drops it after the next user message, the reported input then falls by tens of thousands of tokens and a good run was marked as failed); fixing diagnostics is no longer capped at 6 rounds by the code (the binding sets it); the help chat and the one-shot functions take their round count and output cap from the binding. - Template editor (AI assistant): the task *template from a document* (the tab *Dokument*) has its own round limit, `EDITOR_AI_DOCUMENT_MAX_ITERATIONS` (`Assistant:DocumentMaxIterations`, default 30, 2 to 100). It shared `EDITOR_AI_MAX_ITERATIONS` (default 12, at most 30) with the edits, and converting a PDF with a complex form ended with *Vyčerpán počet kol* before the template was finished. Edits keep `EDITOR_AI_MAX_ITERATIONS`, fixing diagnostics keeps its 6 rounds. The repeated-failure guard still stops a model that sends the same failing call five times. - Template editor (AI assistant): documented that `EDITOR_AI_LOCAL_CONTEXT_TOKENS` is only the editor's budget (the wrap-up request at 75 % and the end of the run at 90 % of the context; nothing is sent to the model) and that a hosted DeepSeek can be set to `1000000`; the samples `deploy/k8s/03-configmap.yaml` and `deploy/compose/.env.sample` say so, and `docker-compose.sample.yml` passes the new variable. Celý seznam změn: CHANGELOG.md v balíčku a https://dev.azure.com/advsoft/Knihovny/_git/NetReporter?path=/src/NetReporter/CHANGELOG.md

Version Downloads Last updated
3.9.2 4 10/28/2026
3.9.1 1 10/27/2026
3.9.0 8 10/20/2026
3.8.1 3 10/19/2026
3.8.0 3 10/19/2026
3.7.0 3 10/19/2026
3.6.0 4 10/17/2026
3.5.1 4 10/15/2026
3.5.0 4 10/15/2026
3.4.2 4 10/15/2026
3.4.0 4 10/12/2026
3.3.0 4 10/11/2026
3.2.2 4 10/10/2026
3.2.1 4 10/10/2026
3.2.0 4 10/10/2026
3.1.1 4 10/09/2026
3.1.0 4 10/09/2026
3.0.1 4 10/08/2026
3.0.0 4 10/08/2026
2.2.1 5 10/05/2026
2.2.0 4 10/05/2026
2.1.0 4 10/04/2026
2.0.1 4 10/04/2026
2.0.0 4 10/03/2026
1.7.0 4 10/03/2026