Files
sw-ads-agent/docs/architecture.md
T

66 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Architecture
## Component map
```mermaid
flowchart TB
subgraph Browser
C[assistant-ui Composer]
T[Thread + Tool UI]
E[Event Timeline]
S[HarnessClientStore]
C --> S
S --> T
S --> E
end
subgraph Server
F[Fastify protocol layer]
R[SessionRegistry]
ES[EventStore]
AB[ApprovalBroker]
AS[AttachmentStore]
MS[ModelConnectionStore]
P[Pi AgentSession]
L[DefaultResourceLoader]
W[SafeWorkspace]
end
S -->|JSON / multipart| F
F -->|SSE| S
F --> R
F --> AS
F --> MS
R --> P
R --> ES
P --> L
P --> AB
P --> W
```
`apps/server` 只做请求校验、错误映射、SSE framing 与对象组合。`packages/harness` 拥有 Agent 生命周期和所有核心状态接口。`packages/shared` 不依赖 Node,定义前后端唯一协议。`apps/web` 不拥有另一套 Agent 状态机,只用 sequence reducer 投影 EventStore。
## Session creation and run
1. Web 创建 Harness Session;服务器建立独立 cwd、事件序列、附件和凭证命名空间。
2. 服务启动时严格加载并缓存 `.env` 默认模型;新 Session 优先使用该配置。没有环境配置时,Web 可把 localStorage 中通过 strict Zod 校验的非敏感模型元数据恢复到该 Session。API Key 不参与浏览器持久化,来自环境变量或服务器 AES-256-GCM 凭证库。
3. 首次 Run 使用精确模型创建独立 Pi `AgentSession``SessionManager.inMemory(cwd)` 与安全 extension。
4. message 立即得到 202;后台调用 `prompt`Pi 事件由单一 adapter 映射并写 EventStore。
5. SSE 将历史和实时事件交给 `HarnessClientStore`assistant-ui External Store Runtime 只负责呈现。
## Storage replacement seams
`EventStore``ApprovalBroker``AttachmentStore``ModelConnectionStore``SessionRegistry` 都有接口。内存/本地临时文件实现可分别替换为 Redis streams、Postgres、对象存储、KMS 与分布式 worker,而不改变 Web 协议。
## Failure and shutdown
Run timeout 和用户 cancel 使用不同 reasonApproval wait 监听同一 AbortSignal。删除先 abort,再 cancel pending approval,关闭订阅与 SSE,调用 Pi `dispose()`,清凭证/附件,最后在 canonical sessions root 校验后删除 cwd。单个 SSE 断开不取消 Run。
## SW Ads daily report
`SkillCatalog.expandCommand` 将精确 `/swads-daily-report` 按需转换为 Pi `<skill>` block,自由文本参数保留,`user.message` 保持原文。Catalog/模型自动匹配不加载该 Skill 正文;`disable-model-invocation` 排除自动发现提示。`skill.requested/loaded``source` 区分 command 和 readcommand 不伪造 toolCallId。只读 Skill resources 在已发现根目录内校验 realpath、普通文件和 symlink 边界。
Pi tools 增加 `swads_cli``render_swads_daily_report`,原有工具和审批不变。`SwadsGateway` 在服务启动时读取并校验环境配置,每个命令创建独立 MCP client/transport,初始化后使用短时能力缓存(60 秒,capabilities 强制刷新),调用结束关闭连接。命令 enum 映射固定远端名,参数先经过本地 strict schema/64 KiB/深度 10 检查,再经远端 inputSchema 验证;需要显式 readOnlyHint,拒绝 destructiveHint。单次调用 30 秒默认超时,响应 2 MiB 上限,AbortSignal 来自当前 Run。Gateway 工具不会注册到 Agent。
每个 Session 的 `SwadsReportTools` 记录当前 Run 的 whoami/catalog/query 成功证据,缺失或必需查询失败禁止 render。Skill 根据返回 columns 名称归一化真实指标,日期、账户、归因和样本限制写入 strict `ReportData`。ReportStore 拥有 accountKey/hash、reportId/UUID 和输出路径,临时目录完整写入后 rename。Chrome 从环境或固定系统路径发现,通过 execFile 启动,5200/9000/24000 三档画布,检查底边与结尾标记后裁切;不完整则降级。
render tool completion 由 Pi adapter 映射到 `report.generated { assistantMessageId, artifact }`。事件只含相对 URL/安全标识/warning,既没有文件正文也没有绝对路径。Web reducer 合并同 Run 的临时 assistant ID,从同源接口获取 PNG 并创建 blob URL,再追加到指定消息(兼容本地 HTTP 部署下 assistant-ui 的图片 URL 校验);Markdown、图片 Dialog 与下载 Tool UI 分工呈现。生成图片是展示产物,不进入模型输入,不受 vision capability 限制。报告 Store 位于 Session Store 之外,重置和删除会话不会删除报告。