sgcWebSockets 2026.10

· Releases
sgcWebSockets 2026.10

sgcWebSockets 2026.10 is out. Three threads run through it: sgcHTML grew the parts a business web application needs and stops you writing by hand, the cryptography went post-quantum without adding a single external library, and a new set of Enterprise authentication components took over the login screen.

Web Applications: the Boring Parts, Done

Sessions, login and CSRF. The new TsgcHTMLAuth component and its session stores keep the cookie, answer the login and logout requests, close idle sessions and throttle failed logins. The CSRF token travels in a meta tag, htmx adds it to every request on its own, and the server rejects a post that does not carry it.

FAuth := TsgcHTMLAuth.Create(Self);
FAuth.SessionStore := TsgcHTMLSessionStore_Memory.Create(Self);
FAuth.CookieName := 'app_session';
FEngine.Auth := FAuth;

Routes that read like routes. Path parameters, a method filter, and access to the headers, the cookies and the body:

with FRouter.Routes.Add do
begin
  Path := '/customers/{id}/edit';
  Methods := [hrmGet, hrmPost];
  RequireLogin := True;
  RequireRoles := 'admin,sales';
end;

Pages you can test. DispatchDirect answers a request with no socket behind it, and a new unit reads the generated HTML, finds elements by id, class, tag or attribute and compares a page against a saved copy, so an unintended change in the markup is noticed by a test rather than by a customer.

Navigation that feels like an application. Pages change without a full reload and keep the scroll position and what the user was typing, with a loading bar, a dialog when the connection drops and a message when a request fails. All of it off by default.

The Four Headline Features

Each of these has an article of its own, linked at the end, so here is only what it is:

Push, Two Ways

Server sent events can now carry the updates instead of a WebSocket, with replay of what was missed while disconnected, and it works with the plain HTTP server. Web Push reaches a browser that is closed. A notification inbox and a preferences table come with them, and the notification component decides which channel a given user gets.

An EventSource Client for Delphi

The new TsgcSSEClient consumes any Server-Sent Events stream and ships in every edition. It reconnects on its own and sends Last-Event-ID, so the server resumes where the stream stopped. The retry: field sent by the server is honoured, OnEvent hands you the event type, the data and the id, and ReconnectOptions adds backoff and jitter. TLS, proxy and authentication are set in OnBeforeConnect, which hands you the HTTP client the component uses.

FSSE := TsgcSSEClient.Create(Self);
FSSE.URL := 'https://example.com/events';
FSSE.ReconnectOptions.Backoff := True;
FSSE.ReconnectOptions.MaxInterval := 30000;
FSSE.ReconnectOptions.Jitter := 0.2;
FSSE.OnEvent := DoSSEEvent;
FSSE.Open;

procedure TForm1.DoSSEEvent(Sender: TObject; const aEvent: TsgcSSEEvent);
begin
  Memo1.Lines.Add(aEvent.EventType + ': ' + aEvent.Data);
end;

The parser behind it, TsgcSSEParser, is public. Feed it the bytes of any text/event-stream in chunks of any size, which is exactly what an LLM streaming response or an MCP Streamable HTTP reply is.

FParser := TsgcSSEParser.Create;
FParser.OnEvent := DoSSEEvent;
FParser.Feed('event: delta' + #10 + 'data: {"text":"Hel"}' + #10#10);

A new demo, Demos\20.HTTP_Protocol\17.SSE_Client_Component, shows it end to end.

AI: Answers You Can Act On

TsgcAIChat can ask for JSON that follows a schema you supply, on OpenAI, Anthropic, Gemini, DeepSeek, Ollama, Grok and Mistral, through the new ChatJSON method, which parses the answer and asks once more with the parse error attached when it cannot be read. The chat component also sends and receives images now, and BaseUrl is honoured by every provider rather than only by Ollama, so any of them can be pointed at a proxy or a local gateway.

Document Extraction: From PDF to Validated JSON

The new TsgcAIDocumentExtractor takes a PDF or an image and a JSON schema, and hands back JSON that has been checked against that schema. OpenAI, Anthropic and Gemini read the PDF directly, the other vision models read images. Built in presets cover invoices, receipts and identity documents (dpInvoice, dpReceipt, dpIDCard), and every field comes with a confidence, so OnLowConfidence tells you which values below MinConfidence deserve a second look. When the answer does not validate, the component asks once more with the errors attached (ValidationRetries).

FExtractor := TsgcAIDocumentExtractor.Create(Self);
FExtractor.AIChat := AIChat1;
FExtractor.Preset := dpInvoice;
FExtractor.MinConfidence := 0.8;
FExtractor.OnLowConfidence := DoLowConfidence;

Memo1.Lines.Text := FExtractor.ExtractFile('invoice.pdf');
if FExtractor.LastResult.FieldConfidence('total') < 0.8 then
  ShowMessage('Check the total by hand');

Link a TsgcAIOCRTesseract, or a TsgcAIOCRWindows that uses the OCR built into Windows 10 and later with nothing to install, and set OCRMode to domFallback or domAlways, and the text is recognised locally first, so even a text only model running on Ollama can do the extraction. For your own prompts, TsgcAIChat gains ChatWithDocument, ChatWithDocumentBase64, ChatWithAttachments and ChatJSONWithAttachments, which send one or several files, held in a TsgcAIChatAttachments list, with the message.

A Voice Agent That Listens, Talks Back and Calls Tools

The new TsgcAIVoiceAgent is one component that listens, detects when the user has finished a turn, answers with its own voice and calls your tools, over OpenAI Realtime or Gemini Live. It speaks WebSocket, or WebRTC with OpenAI, and runs on Windows, Android and iOS. Turns are detected by server VAD, semantic VAD, a client side VAD or by hand (vtdServerVAD, vtdSemanticVAD, vtdClientVAD, vtdManual). With BargeIn the user can interrupt, and the agent stops talking and truncates its answer where it was cut off. OnTranscript delivers live transcripts of both the user and the agent.

FAgent := TsgcAIVoiceAgent.Create(Self);
FAgent.Provider := vapOpenAI;
FAgent.OpenAIOptions.ApiKey := 'sk-...';
FAgent.Instructions := 'You are the shop assistant. Keep answers short.';
FAgent.TurnDetection.Mode := vtdSemanticVAD;
FAgent.BargeIn := True;

oTool := FAgent.Tools.Add;
oTool.Name := 'find_product';
oTool.Description := 'Looks up a product by name';
oTool.Parameters :=
  '{"type":"object","properties":{"name":{"type":"string"}}}';

FAgent.OnTranscript := DoTranscript;
FAgent.OnToolCall := DoToolCall;
FAgent.Start;

procedure TForm1.DoToolCall(Sender: TObject; const aCallId, aName,
  aArguments: string; var aResult: string; var aHandled: Boolean);
begin
  if aName = 'find_product' then
  begin
    aResult := FindProduct(aArguments);
    aHandled := True;
  end;
end;

Tools come from OnToolCall, and when a TsgcWSAPI_Client_MCP is assigned to MCPClient the tools of that MCP server are offered to the model automatically. For telephony, Audio.Format switches to G.711 mu-law or A-law at 8 kHz (vafG711ULaw, vafG711ALaw). The voice agent is available for Delphi 7 to Delphi 13 and for .NET, and a new demo turns it into a voice shop assistant over a TDataSet.

Cryptography: Post-Quantum, in Object Pascal

ML-KEM (FIPS 203), ML-DSA (FIPS 204) and SLH-DSA (FIPS 205), X-Wing hybrid key encapsulation, post-quantum X.509 certificates and certificate authorities, and JWT signed with ML-DSA. All of it written in Object Pascal in the sgcCrypto pack, with no external library, validated against the NIST known answer vectors.

On top of that sits a native TLS 1.3 and TLS 1.2 engine, also pure Pascal: a client or a server speaks TLS without OpenSSL and without SChannel, negotiating the hybrid post-quantum groups of RFC 10024, with ALPN, S N I, client certificates and optional use of the operating system trust store. TLS 1.2 is there for the peers that cannot do TLS 1.3 yet, with forward secret AES-GCM and ChaCha20-Poly1305 suites by default, extended master secret and downgrade protection, and TLSOptions.Version sets the lowest version allowed. The hybrid groups stay on TLS 1.3.

The classical side was hardened in the same pass: blinded constant time RSA, constant time elliptic curve scalar multiplication and Ed25519, table free AES and GHASH, imported private keys checked against their public half, and non minimal DER signatures rejected.

Authentication: the Login Everyone Asks For

A new set of authentication components answers the questions every customer asks about the login screen. They ship in the Enterprise and All-Access editions and in the sgcAuth pack, and the same components are part of sgcWebSockets .NET.

Fixes Worth Naming

.NET

The .NET library keeps pace: auth and sessions with a ClaimsPrincipal bridge for ASP.NET Core, the router, the testing helpers, SPA navigation, the SSE transport with a native endpoint, structured output, document extraction with both OCR engines, the realtime voice agent, the AI Data Pack, Web Push, MCP Apps, the CRUD component with its adapters and the new TsgcSSEClient, all with the same API names as Delphi.

Razor Tag Helpers for ASP.NET Core. sgcHTML now fits an MVC or Razor Pages application the way Telerik UI and DevExpress do. Tag Helpers such as <sgc-grid>, <sgc-form>, <sgc-autocomplete>, <sgc-dialog> and <sgc-chart>, and their fluent twins under Html.Sgc(), render Bootstrap 5 on the server and talk to your controllers over htmx, with no JavaScript framework. The grid pages, sorts, filters, searches and exports to XLSX and PDF over an IQueryable, so EF Core runs it all as SQL:

<sgc-grid name="orders" key="Id" items="Model"
          asp-action="Read" asp-export-action="Export" export="xlsx,pdf"
          page-size="15" sortable="true" filterable="true"
          searchable="true" push-url="true">
    <sgc-column field="Reference" searchable="true" />
    <sgc-column field="Customer" searchable="true" />
    <sgc-column field="OrderDate" title="Date" format="{0:yyyy-MM-dd}" filter="range" />
    <sgc-column field="Total" format="{0:N2}" align="right" filter="range" />
</sgc-grid>

// OrdersController
public IActionResult Read(SgcDataRequest request) => this.SgcGrid(request, Rows());

Inputs bind with asp-for and show the ModelState errors, and this.SgcCloseDialog("edit-order", refresh: "orders") closes an edit dialog and reloads the grid. The part the others do not have is server push: a chart with live="true" redraws in every open browser when a background service calls hub.BroadcastChartAsync(...), over the sgcHTML WebSocket and with no SignalR code. It ships in the esegece.sgcHTML.AspNetCore NuGet package, Community edition included, and the 22.RazorMvc demo is the familiar orders sample rebuilt with it.

Upgrading

Everything new is additive and off by default. Drop in the new units, rebuild your packages, and an existing application behaves exactly as it did.

The Long Versions

Watch It

There is a short video of this on the eSeGeCe channel.

Questions, feedback or migration help? Get in touch — you will get a reply from the people who wrote the code.