sgcWebSockets 2026.10 发布了。这个版本贯穿着三条主线:sgcHTML 补齐了一个商业级 Web 应用需要的部分,让你不用再手写这些代码;密码学也在没有引入任何一个外部库的情况下迈向了后量子时代;而一组全新的 Enterprise 认证组件接管了登录界面。
Web 应用:繁琐的部分,搞定了
会话、登录与 CSRF。新的 TsgcHTMLAuth 组件及其会话存储负责维护 cookie、响应登录和登出请求、关闭空闲会话,并对失败的登录进行限流。CSRF 令牌放在一个 meta 标签里,htmx 会自动把它加到每个请求上,服务器则会拒绝不携带它的 post 请求。
FAuth := TsgcHTMLAuth.Create(Self);
FAuth.SessionStore := TsgcHTMLSessionStore_Memory.Create(Self);
FAuth.CookieName := 'app_session';
FEngine.Auth := FAuth;
读起来就像路由的路由。路径参数、方法过滤器,以及对请求头、cookie 和请求体的访问:
with FRouter.Routes.Add do
begin
Path := '/customers/{id}/edit';
Methods := [hrmGet, hrmPost];
RequireLogin := True;
RequireRoles := 'admin,sales';
end;
可以测试的页面。DispatchDirect 可以在没有底层 socket 的情况下应答一个请求,一个新的单元会读取生成的 HTML,按 id、类、标签或属性查找元素,并把一个页面与保存的副本进行比较,这样标记中一次无意的改动会被测试发现,而不是被客户发现。
感觉像原生应用的导航。页面切换不需要完全重新加载,并会保留滚动位置和用户正在输入的内容,还带有加载进度条、连接断开时的提示框,以及请求失败时的消息。所有这些功能默认都是关闭的。
在窗体上设计页面,零代码。在 VCL 窗体上放置一个 TsgcWebSocketHTTPServer、一个 TsgcHTMLDesignServer、一个 TsgcHTMLDesignSurface 和若干 sgcHTML 组件,唯一需要写的一行就是 WSServer.Active := True。design server 根据窗体构建页面,并从可执行文件中提供 Bootstrap、htmx 和 Chart.js。Surface 的 action 会在用户点击或提交时运行 Delphi 代码:在对象检查器中设置 Source 和 Target,双击 OnExecute,目标就会就地更新,无需重新加载页面。Demos\60.HTML\00.QuickStart 中的六个 QuickStart 演示会一步一步地讲解,入门指南(PDF,英文)对它们做了说明,而 sgcHTML 快速入门则展示了 5 分钟上手的路径。
四个重点新功能
每一项都有单独的文章介绍,链接在文末,这里只说它是什么:
- MCP Apps。一个用页面而不是段落来应答的 MCP 工具,可以在 ChatGPT、Claude 或 VS Code 中渲染,由和其他 sgcHTML 页面相同的组件构建而成。
- AI 页面生成器。描述一个页面,或者给设计器一张截图,它就会用你已注册的组件把页面构建出来,作为一个你可以接受或放弃的候选方案。
- CRUD 组件。列表、搜索、分页、表单、删除,以及一个数据集的写入路径,可以基于 TDataSet,也可以基于你自己的 SQL,并配有 IDE 向导和命令行生成器。
- AI Data Pack。用自然语言向一个 grid、一个数据表或一个数据透视表提问,内置的基于规则的解析器在完全没有 API key 的情况下也能作答。
推送,两种方式
服务器发送事件(server sent events)现在可以取代 WebSocket 来传送更新,并能在断线期间重放错过的内容,而且它可以配合普通的 HTTP 服务器工作。Web Push 则可以触达一个已经关闭的浏览器。它们还带来了一个通知收件箱和一个偏好设置表,通知组件会决定某个用户走哪条通道。
面向 Delphi 的 EventSource 客户端
全新的 TsgcSSEClient 可消费任意 Server-Sent Events 流,并在所有版本中提供。它会自行重新连接并发送 Last-Event-ID,让服务器从流中断的位置继续。服务器发送的 retry: 字段会被遵循,OnEvent 会把事件类型、数据和 id 交给您,ReconnectOptions 则加入了退避和抖动。TLS、代理和身份验证在 OnBeforeConnect 中设置,该回调会把组件所使用的 HTTP 客户端交给您。
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;
它背后的解析器 TsgcSSEParser 是公开的。把任意 text/event-stream 的字节以任意大小的分块喂给它即可,而这正是 LLM 流式响应或 MCP Streamable HTTP 响应的样子。
FParser := TsgcSSEParser.Create;
FParser.OnEvent := DoSSEEvent;
FParser.Feed('event: delta' + #10 + 'data: {"text":"Hel"}' + #10#10);
新增的演示 Demos\20.HTTP_Protocol\17.SSE_Client_Component 完整展示了整个流程。
AI:可以直接拿来用的答案
TsgcAIChat 现在可以通过新的 ChatJSON 方法,在 OpenAI、Anthropic、Gemini、DeepSeek、Ollama、Grok 和 Mistral 上请求遵循你提供的 schema 的 JSON;该方法会解析返回结果,当解析失败时会附上解析错误再问一次。聊天组件现在也能发送和接收图片了,而且 BaseUrl 现在对每个提供商都生效,而不再只对 Ollama 生效,这样它们中的任何一个都可以指向一个代理或本地网关。
文档提取:从 PDF 到经过校验的 JSON
新增的 TsgcAIDocumentExtractor 接收一个 PDF 或图片以及一个 JSON schema,返回按该 schema 校验过的 JSON。OpenAI、Anthropic 和 Gemini 直接读取 PDF,其他视觉模型读取图片。内置预设覆盖发票、收据和身份证件(dpInvoice、dpReceipt、dpIDCard),每个字段都带有置信度,因此 OnLowConfidence 会告诉您哪些低于 MinConfidence 的值值得再核实一遍。当答案未通过校验时,组件会带着错误信息再问一次(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');
关联一个 TsgcAIOCRTesseract,或者关联使用 Windows 10 及更高版本内置 OCR、无需安装任何东西的 TsgcAIOCRWindows,并把 OCRMode 设为 domFallback 或 domAlways,文本就会先在本地被识别,这样即使是运行在 Ollama 上的纯文本模型也能完成提取。若要使用自己的提示词,TsgcAIChat 新增了 ChatWithDocument、ChatWithDocumentBase64、ChatWithAttachments 和 ChatJSONWithAttachments,它们会随消息发送一个或多个文件,这些文件保存在 TsgcAIChatAttachments 列表中。
一个会听、会说、还会调用工具的语音代理
全新的 TsgcAIVoiceAgent 是一个组件,它能倾听、检测用户何时说完一轮、用自己的声音回答并调用您的工具,通过 OpenAI Realtime 或 Gemini Live 实现。它使用 WebSocket 通信,或者与 OpenAI 之间使用 WebRTC,并可在 Windows、Android 和 iOS 上运行。轮次检测支持服务器端 VAD、语义 VAD、客户端 VAD 或手动方式(vtdServerVAD、vtdSemanticVAD、vtdClientVAD、vtdManual)。通过 BargeIn,用户可以打断,代理会停止说话,并在被打断处截断其回答。OnTranscript 会提供用户和代理双方的实时转写。
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;
工具来自 OnToolCall,当一个 TsgcWSAPI_Client_MCP 被赋值给 MCPClient 时,该 MCP 服务器的工具会自动提供给模型。对于电话场景,Audio.Format 会切换到 8 kHz 的 G.711 mu-law 或 A-law(vafG711ULaw、vafG711ALaw)。该语音代理适用于 Delphi 7 到 Delphi 13 以及 .NET,新增的演示把它变成了一个基于 TDataSet 的语音商店助手。
MCP:2026-07-28 规范
MCP 服务器和客户端现在支持 Model Context Protocol 的 2026-07-28 修订版。同一个服务器既能应答新的无状态客户端,也能应答 VS Code 和 Claude 等现有的 2025-11-25 客户端,因此你现有的客户端无需任何改动。在客户端上,将 MCPOptions.ProtocolEra 设为 Auto 时,会先尝试新协议,服务器不支持时自动回退,并按服务器记住结果。
- 发现与请求头。
server/discover、随每个请求发送的协议版本和客户端详情、由服务器检查的Mcp-Method和Mcp-Name请求头、列表结果上的缓存提示,以及新的错误码。标记了x-mcp-header的工具参数会作为请求头传输。 - 一个流承载所有变化。通过
subscriptions/listen,客户端打开一个长连接流,即可接收工具、提示和资源列表的变化以及资源更新。你已经在调用的 Send notification 方法同样会送达这些客户端。 - 多轮往返请求。工具、提示或资源可以向客户端请求输入,例如表单、网页、AI 回答或客户端 roots,并在客户端带着答案再次调用时继续执行。两次调用之间保存的状态经过签名并会过期(
MCPOptions.MRTR)。在客户端上,由OnMCPInputRequired来应答,而现有的 roots、sampling 和 elicitation 处理程序会自行应答。 - 任务。长时间运行的工具会返回一个任务,客户端会持续跟踪直到它完成,在任务需要输入时作出回答,也可以取消。服务器端使用
MCPOptions.Tasks和CreateTask,客户端使用OnMCPTaskCreated、OnMCPTaskStatus和OnMCPTaskCompleted。 - 客户端授权。启用
MCPOptions.Authorization后,401 不再是终点:客户端会自行找到授权服务器,通过客户端 ID 元数据文档或动态注册完成注册,使用 PKCE 登录,检查颁发者,并在令牌过期时刷新令牌。
密码学:用 Object Pascal 实现的后量子能力
ML-KEM(FIPS 203)、ML-DSA(FIPS 204)和 SLH-DSA(FIPS 205)、X-Wing 混合密钥封装、后量子 X.509 证书与证书颁发机构,以及用 ML-DSA 签名的 JWT。这一切都用 Object Pascal 写在 sgcCrypto 包里,不依赖任何外部库,并针对 NIST 的已知答案向量做了验证。
在此之上是一个原生 TLS 1.3 和 TLS 1.2 引擎,同样是纯 Pascal 实现:客户端或服务器无需 OpenSSL、也无需 SChannel 就能进行 TLS 通信,协商 RFC 10024 中的混合后量子分组,并支持 ALPN、S N I、客户端证书,以及可选地使用操作系统的信任存储。TLS 1.2 是为那些还无法使用 TLS 1.3 的对端准备的,默认提供具有前向保密性的 AES-GCM 和 ChaCha20-Poly1305 套件、扩展主密钥和降级保护,TLSOptions.Version 用于设置允许的最低版本。混合分组仍然只存在于 TLS 1.3 中。
经典算法也在同一轮改动中得到了加固:带盲化的常数时间 RSA、常数时间的椭圆曲线标量乘法与 Ed25519、无查找表的 AES 和 GHASH、导入的私钥会与其公钥部分做校验,以及拒绝非最小编码的 DER 签名。
服务器端的 TLS,随你所需
同一端口上的明文与 TLS。SSLOptions.AllowPlainText 让 TLS 服务器也能在同一端口上接受普通 HTTP 和 WebSocket 连接,并根据客户端发送的第一个字节区分它们。SSLOptions.PlainTextPolicy 可以直接提供服务、用 308 重定向到 https,或用 400 拒绝;Server.IsTLS(AContext) 则在 OnCommandGet 中告诉你请求来自哪种传输。它适用于默认、IOCP 和 EPOLL 三种 IOHandler。
用 HSTS 拿到 A+。SecurityOptions.HSTS_Options 会在通过 TLS 发送的每个响应中添加 Strict-Transport-Security 头,这正是 SSL Labs 给出 A+ 评级所需要的。它绝不会通过普通 HTTP 发送,并且当你的代码已经设置过它时,也不会重复添加。
使用你自己的 TLS 库。IOCP 和 EPOLL 服务器不再与 OpenSSL 绑定。为你的库编写一个 TLS 提供程序,例如 SecureBlackbox,事件驱动引擎就会像驱动内置引擎一样驱动它。
认证:每个客户都在要的登录
一组全新的认证组件回答了每个客户关于登录界面的问题。它们随 Enterprise 和 All-Access 版本以及 sgcAuth 包提供,相同的组件也是 sgcWebSockets .NET 的一部分。
- Passkey。WebAuthn 服务端可以在用户不输入用户名的情况下完成登录,在浏览器自带的自动填充列表中提示 Passkey,为每个用户保留多个 Passkey,区分已同步的 Passkey 和绑定单一设备的 Passkey,并触发事件,让凭据保存在你自己的数据库里。
- SAML 单点登录。
TsgcSAMLServiceProvider让你的应用成为面向 Entra ID、Okta、AD FS、Google Workspace、Keycloak 或任何其他身份提供商的 SAML 2.0 服务提供方。 - Active Directory 与 LDAP。
TsgcLDAPClient通过 LDAPS 或 StartTLS 用目录密码验证用户,并读取其所属组,包括嵌套组。 - 身份验证器应用的验证码。
TsgcTOTPAuthenticator生成并校验 Google Authenticator、Microsoft Authenticator 等应用的验证码,包含用于二维码的注册链接、防重放保护和恢复码。 - OpenID Connect。
TsgcHTTP_OIDC_Client通过发现文档在任何 OpenID 提供商处完成登录,并验证到达你自己 API 的 ID 令牌和 bearer 令牌。 - 不保存密码的邮件。
TsgcMailOAuth2获取并刷新 SMTP、IMAP 和 POP3 如今所要求的 Microsoft 365 与 Gmail OAuth2 令牌。
积少成多的小改进
- 从右到左的页面。对于阿拉伯语、希伯来语、波斯语、乌尔都语以及其他从右到左的语言,sgcHTML 页面会自动切换为从右到左的布局,加载库中现已包含的从右到左 Bootstrap 样式表,并把组件从侧边栏到网格整体镜像。需要时,可以用
HtmlDir和Dir强制指定方向。新增演示 22.RTL。 - 地理定位。
TsgcHTMLComponent_Geolocation可以一次性或持续读取浏览器的 GPS 位置,并把纬度、经度、精度、海拔、方向和速度发送到服务器。 - 在服务器上排序和过滤的网格。
SortMode := gsmServer和ServerFilter通过 htmx 发送排序条件,以及每一列各自的过滤输入,每列可使用文本过滤或范围过滤(gfkText、gfkRange)。分页和 AutoComplete 也获得了基于普通 HTTP 的同样 htmx 路径。 - iPhone 上的相机扫描。
PolyfillURL会在没有内置条码解码器的浏览器上加载一个条码解码器,RedirectURL则会打开一个带有扫描结果的页面。 - Lazarus。sgcHTML 运行时演示现已支持 Lazarus 和 Free Pascal,Lazarus 包中也包含了 CRUD 和 MCP Apps 单元。
- 为什么我被拒绝了?当服务器拒绝 WebSocket 连接时,例如令牌已过期而返回 401,可以在
OnException中通过TsgcWSConnectionClient(Connection).HandshakeResponseBody获取其应答的正文。 - 在连接线程上处理你自己的数据。
QueueOptions.DrainedMode := qdmEveryPass会在连接循环的每一轮中、在连接自己的线程上触发OnQueueDrained,这样应用程序就可以从那里发送待发送的数据。 - WinHTTP 上的保活。WinHTTP WebSocket 客户端新增了
OnBeforeHeartBeat,可在每个 HeartBeat 间隔发送你自己的保活消息。 - AI Chat。
ImageOutput让 Gemini 可以用图像来回答,并在后续每条消息中继续编辑这些图像;OpenAI 的图像编辑请求支持 gpt-image-1 选项和多张输入图像;TLSOptions用于选择提供商请求所使用的 OpenSSL 版本。 - OpenAPI 客户端。
TsgcOpenAPI_Client.UserAgent用于设置每个请求的 User-Agent 头,为空时则不发送该头。
值得一提的修复
- 使用 RSA 和 ECDSA 密钥进行 JWT 签名与验证时,以及在静态链接 OpenSSL 的 32 位应用中,存在的内存损坏问题。
- SChannel 处理程序在每次使用 PFX 文件建立连接时,都会在 Windows 密钥存储中留下一份私钥副本,并且在较新版本的 Windows 上不会发送客户端证书。
- 使用 Windows 存储中证书的并发 SChannel 连接握手失败。
- OAuth2 服务器会拒绝用 RSA 密钥签名的 DPoP 证明。
- CloudFront 签名 URL 的签名没有做 URL 安全编码。
.NET
.NET 库同步跟进:为 ASP.NET Core 提供 ClaimsPrincipal 桥接的身份验证与会话管理、路由器、测试辅助工具、SPA 导航、带原生端点的 SSE 传输、结构化输出、带两种 OCR 引擎的文档提取、实时语音代理、AI Data Pack、Web Push、MCP Apps、带适配器的 CRUD 组件,以及全新的 TsgcSSEClient,全部使用与 Delphi 相同的 API 名称。
面向 ASP.NET Core 的 Razor Tag Helpers。sgcHTML 现在可以像 Telerik UI 和 DevExpress 那样融入 MVC 或 Razor Pages 应用。<sgc-grid>、<sgc-form>、<sgc-autocomplete>、<sgc-dialog> 和 <sgc-chart> 等 Tag Helper,以及 Html.Sgc() 下与之对应的流式写法,会在服务器端渲染 Bootstrap 5,并通过 htmx 与您的控制器通信,无需 JavaScript 框架。网格在 IQueryable 上完成分页、排序、筛选、搜索,并可导出为 XLSX 和 PDF,因此 EF Core 会把这一切都作为 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());
输入控件通过 asp-for 绑定并显示 ModelState 错误,this.SgcCloseDialog("edit-order", refresh: "orders") 会关闭编辑对话框并重新加载网格。其他产品所没有的是服务器推送:当后台服务调用 hub.BroadcastChartAsync(...) 时,带有 live="true" 的图表会在每个打开的浏览器中重绘,通过 sgcHTML WebSocket 完成,无需任何 SignalR 代码。它包含在 esegece.sgcHTML.AspNetCore NuGet 包中,Community 版同样可用,22.RazorMvc 演示就是用它重建的、大家熟悉的订单示例。
升级
所有新增功能都是增量式的,并且默认关闭。加入新的单元、重新编译你的包,现有应用的行为将与之前完全一致。
完整版文章
- 在 ChatGPT 和 Claude 中运行你的 Delphi 应用
- 把一张截图变成一个 Delphi 网页
- 不依赖 OpenSSL DLL 的 Delphi TLS 1.3
- 五分钟构建一个 Delphi Web CRUD 页面
- 用简单英语向你的 Delphi 表格提问
- 从 Delphi 触达一个已经关闭的浏览器
- Passkey、SAML SSO、LDAP 与 TOTP 双因子认证:Delphi 登录组件
- 在 Delphi 中通过 Entra ID、Okta 和 AD FS 实现 SAML 单点登录
- Delphi 中的 Passkey:用 WebAuthn 实现无密码登录
观看视频
关于此功能的简短视频发布在eSeGeCe 频道上。
有问题、反馈,或需要迁移方面的帮助?欢迎联系我们 — 你会收到编写这些代码的人的回复。
