fix(telegram): address review findings

- A speech or download timeout (TaskCanceledException nobody asked for) is a failure
  with the user notice, not a silent shutdown; OpenAiSpeechToText maps it to
  "the request timed out."; UpdateRouter only treats the caller's cancellation as shutdown.
- send: WorkspacePaths resolves the real path component by component (realpath),
  closing the directory-link-inside-target bypass; `.` reports a directory.
- Image documents are attached inline only when their magic bytes are JPEG/PNG/GIF/WebP,
  under the detected type.
- Audio goes to STT as an ASCII audio.<ext> name.
- MCP Browser section mentions send only when it is active.
- RunInOrderAsync takes a cancellation token; queued work is skipped once disposal gives up;
  SendReplyAsync stays private behind ReplyInOrderAsync.
- Speech HttpClient handler recycles pooled connections; BuiltInTools.Send();
  IExtensionHost.Channel is abstract; WorkspacePaths in its own file.
- Tests: timeouts, symlink chains (Linux), sniffing, channel delivery failures,
  queued-work cancellation, gated voice ordering. Spec and docs updated.
This commit is contained in:
EugeneTes
2026-09-26 22:35:20 +02:00
parent c5ecd017a0
commit 6ab98a8155
25 changed files with 536 additions and 93 deletions

View File

@@ -129,7 +129,7 @@ public sealed class McpExtension : IExtension
private void AddPromptSections(IExtensionApi api, SystemPromptOptions options)
{
var active = api.GetActiveTools().ToHashSet(StringComparer.Ordinal);
var hasSend = api.GetAllTools().Any(t => t.Name == "send");
var hasSend = active.Contains("send"); // registered but inactive: the model can't call it
foreach (var server in _servers)
{
if (!server.RegisteredTools.Any(active.Contains)) continue;