167 lines
5.6 KiB
Markdown
167 lines
5.6 KiB
Markdown
# 服务子系统设计 — 其他服务子系统
|
|
|
|
## 元数据
|
|
- 项目名称: free-code
|
|
- 文档类型: 服务子系统设计
|
|
- 原始代码来源: `../../src/services/`
|
|
- 关联总览: [服务子系统设计总览](服务子系统设计.md)
|
|
- 原始映射: [原始代码映射](reference/原始代码映射-服务子系统.md)
|
|
- 相关模块: [基础设施设计 — 后台任务管理](../基础设施设计/基础设施设计-后台任务管理.md)
|
|
- 相关模块: [UI与扩展设计 — 特性开关系统](../UI与扩展设计/UI与扩展设计-特性开关系统.md)
|
|
|
|
## 21.1 远程会话
|
|
|
|
```csharp
|
|
public interface IRemoteSessionManager
|
|
{
|
|
Task ConnectAsync(string endpoint, CancellationToken cancellationToken = default);
|
|
Task DisconnectAsync(CancellationToken cancellationToken = default);
|
|
IAsyncEnumerable<RemoteEvent> ReadEventsAsync(CancellationToken cancellationToken = default);
|
|
}
|
|
|
|
public abstract record RemoteEvent(DateTimeOffset Timestamp);
|
|
public sealed record RemoteConnectedEvent(DateTimeOffset Timestamp, string SessionId) : RemoteEvent(Timestamp);
|
|
public sealed record RemoteDisconnectedEvent(DateTimeOffset Timestamp, string Reason) : RemoteEvent(Timestamp);
|
|
public sealed record RemoteMessageEvent(DateTimeOffset Timestamp, string Message) : RemoteEvent(Timestamp);
|
|
|
|
public enum RemoteConnectionStatus
|
|
{
|
|
Disconnected,
|
|
Connecting,
|
|
Connected,
|
|
Reconnecting,
|
|
Failed
|
|
}
|
|
```
|
|
|
|
远程会话管理用于把本地交互扩展到远端主机或托管环境,并通过事件流表达连接状态、消息和断连原因。
|
|
|
|
## 21.2 语音输入
|
|
|
|
```csharp
|
|
public interface IVoiceService
|
|
{
|
|
Task StartAsync(CancellationToken cancellationToken = default);
|
|
Task StopAsync(CancellationToken cancellationToken = default);
|
|
Task<string?> RecognizeAsync(CancellationToken cancellationToken = default);
|
|
}
|
|
|
|
public sealed class VoiceService : IVoiceService
|
|
{
|
|
public Task StartAsync(CancellationToken cancellationToken = default) => Task.CompletedTask;
|
|
public Task StopAsync(CancellationToken cancellationToken = default) => Task.CompletedTask;
|
|
public Task<string?> RecognizeAsync(CancellationToken cancellationToken = default) => Task.FromResult<string?>(null);
|
|
}
|
|
```
|
|
|
|
语音输入采用特性开关与 OAuth 门控:只有启用对应功能且完成授权后,语音能力才会暴露给会话流程。
|
|
|
|
## 21.3 通知服务
|
|
|
|
```csharp
|
|
public interface INotificationService
|
|
{
|
|
Task NotifyAsync(string title, string message, CancellationToken cancellationToken = default);
|
|
bool IsSupportedTerminal();
|
|
}
|
|
|
|
public sealed class NotificationService : INotificationService
|
|
{
|
|
public Task NotifyAsync(string title, string message, CancellationToken cancellationToken = default)
|
|
=> Task.CompletedTask;
|
|
|
|
public bool IsSupportedTerminal()
|
|
{
|
|
var terminal = Environment.GetEnvironmentVariable("TERM_PROGRAM") ?? string.Empty;
|
|
return terminal is "iTerm2" or "Kitty" or "Ghostty";
|
|
}
|
|
}
|
|
```
|
|
|
|
通知服务依赖终端类型检测,在 iTerm2、Kitty、Ghostty 等环境中可提供更稳定的本地通知体验。
|
|
|
|
## 21.4 限流服务
|
|
|
|
```csharp
|
|
public interface IRateLimitService
|
|
{
|
|
bool CanProceed(IDictionary<string, string> headers);
|
|
TimeSpan? GetRetryAfter(IDictionary<string, string> headers);
|
|
}
|
|
|
|
public sealed class RateLimitService : IRateLimitService
|
|
{
|
|
public bool CanProceed(IDictionary<string, string> headers)
|
|
=> !GetRetryAfter(headers).HasValue;
|
|
|
|
public TimeSpan? GetRetryAfter(IDictionary<string, string> headers)
|
|
{
|
|
foreach (var pair in headers)
|
|
{
|
|
if (pair.Key.StartsWith("anthropic-ratelimit-tokens-", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return TimeSpan.FromSeconds(30);
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
```
|
|
|
|
限流服务通过解析 `anthropic-ratelimit-tokens-*` 头部推断令牌配额状态,并用于动态退避与重试控制。
|
|
|
|
## 21.5 伙伴系统
|
|
|
|
```csharp
|
|
public interface ICompanionService
|
|
{
|
|
Companion Create(string seed);
|
|
}
|
|
|
|
public sealed class CompanionService : ICompanionService
|
|
{
|
|
public Companion Create(string seed)
|
|
{
|
|
var prng = new Mulberry32(seed.GetHashCode());
|
|
return new Companion(
|
|
Species: Species.Cat,
|
|
Eye: Eye.Blue,
|
|
Hat: Hat.Bowler,
|
|
Rarity: Rarity.Rare,
|
|
Name: $"Companion-{prng.NextInt(1000)}");
|
|
}
|
|
}
|
|
|
|
public sealed class Mulberry32
|
|
{
|
|
private uint _state;
|
|
public Mulberry32(int seed) => _state = (uint)seed;
|
|
public int NextInt(int max) => (int)(NextUInt() % (uint)max);
|
|
private uint NextUInt()
|
|
{
|
|
_state += 0x6D2B79F5;
|
|
var t = _state;
|
|
t = (t ^ (t >> 15)) * (t | 1);
|
|
t ^= t + (t ^ (t >> 7)) * (t | 61);
|
|
return t ^ (t >> 14);
|
|
}
|
|
}
|
|
|
|
public sealed record Companion(Species Species, Eye Eye, Hat Hat, Rarity Rarity, string Name);
|
|
|
|
public enum Species { Cat, Dog, Fox, Owl }
|
|
public enum Eye { Blue, Green, Gold, Red }
|
|
public enum Hat { None, Bowler, Cap, Crown }
|
|
public enum Rarity { Common, Uncommon, Rare, Epic, Legendary }
|
|
```
|
|
|
|
伙伴系统使用确定性生成逻辑:相同种子输入会产生相同角色结果,便于同步、复现和测试。
|
|
|
|
## 21.6 交叉引用
|
|
- [服务子系统设计总览](服务子系统设计.md)
|
|
- [原始代码映射](reference/原始代码映射-服务子系统.md)
|
|
- [核心模块设计 — 查询引擎](../核心模块设计/核心模块设计-查询引擎-QueryEngine.md)
|
|
- [基础设施设计 — 后台任务管理](../基础设施设计/基础设施设计-后台任务管理.md)
|
|
- [UI与扩展设计 — 特性开关系统](../UI与扩展设计/UI与扩展设计-特性开关系统.md)
|