背景
Agent Tracking Phase 2。Phase 1 (#16) 已定义契约。本 issue 实现 Worker 端的接收通道 + PTY spawn 时的 PATH shim 注入。
范围
Worker loopback HTTP endpoint:
- `src/Worker/CortexTerminal.Worker/Agent/AgentEventEndpoint.cs` — Kestrel 仅 127.0.0.1 监听
- 端口选随机空闲(写进 `CortexTerminal:AgentEventPort` 配置)
- POST `/agent-event`:解析 JSON,按 `agent_kind` 字段找到对应 `IAgentAdapter`,调 `ParseEventAsync`,转发给 Gateway
Adapter 接口:
- `src/Worker/CortexTerminal.Worker/Agent/IAgentAdapter.cs` — `Kind / ResolveBinary / BuildEnvironment / GenerateHookConfig / ParseEvent`
- `src/Worker/CortexTerminal.Worker/Agent/AgentSessionContext.cs` — record `SessionId / HookUrl / WorkDir / TempConfigDir`
PTY spawn env vars 注入(`UnixPtyHost.cs:42-79` / `WindowsPtyHost.cs`):
- `CORTERM_SESSION_ID` — PTY 的 sessionId
- `CORTERM_AGENT_HOOK_URL=http://127.0.0.1:/agent-event`
- `CORTERM_ORIGINAL_PATH` — 原始 PATH(corterm-agent 用它跳过 shim 找真二进制)
- `PATH=/shims:$PATH` — 最关键,让 `claude` 命中 shim
shim 目录(Worker 启动时确保存在 `/shims/`):
- `claude` (sh)、`claude.cmd` (Windows)
- `codex` (sh)、`codex.cmd`
- `opencode` (sh)、`opencode.cmd`
- 每个 shim 调 `exec corterm-agent "$@"`
SignalR pipeline:
- Worker gateway client 加 `ForwardAgentActivityAsync(frame)`
- Gateway `WorkerHub` 加 `ForwardAgentActivity` handler,落库 `SessionAgentEventEntity` + 转推给 attached 客户端
验收
- Worker 启动后 `/shims/` 目录及 6 个 shim 文件存在
- PTY 里 `echo $PATH` 看到 shim 目录在最前
- `echo $CORTERM_SESSION_ID` 能拿到 sessionId
- 模拟 POST 一个 `AgentStartedFrame` 到 endpoint,Gateway 能收到 `SessionAgentEvent` 记录
依赖
不做的事
背景
Agent Tracking Phase 2。Phase 1 (#16) 已定义契约。本 issue 实现 Worker 端的接收通道 + PTY spawn 时的 PATH shim 注入。
范围
Worker loopback HTTP endpoint:
Adapter 接口:
PTY spawn env vars 注入(`UnixPtyHost.cs:42-79` / `WindowsPtyHost.cs`):
shim 目录(Worker 启动时确保存在 `/shims/`):
SignalR pipeline:
验收
依赖
不做的事