Metadata-Version: 2.4
Name: ennew-harness-sdk
Version: 0.1.5
Summary: Ennew Harness 业务上下文与前端消息 Python SDK
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# Ennew Harness Python SDK

适用于 Python 3.9 及以上版本，安装包名为 `ennew-harness-sdk`，导入名称为 `ennew_harness`。

从 `0.1.1` 起，导入名称由 `harness` 改为 `ennew_harness`，避免与 Worker 自身的同名包冲突。升级后请同步修改业务脚本中的导入语句；不保留旧名称别名。

```bash
python3 -m pip install --upgrade ennew-harness-sdk
```

本 SDK 依赖 Ennew Harness 运行环境，并非独立运行的公共网关客户端。普通脚本读取上下文或发送前端消息时，运行时必须提供 `CODEX_THREAD_ID`；MCP 读取上下文可改为传入请求 `ctx`。读取上下文还需设置 `ENV` 或 `HARNESS_ENV`，并能访问对应业务网关。发送前端消息需要本机 Worker 服务。

读取上下文时，Worker 还需通过环境变量 `HARNESS_GATEWAY_CONTEXT_TOKEN` 注入对应环境的服务凭据。SDK 将其放入 `X-OpenClaw-Mcp-Gateway-Token` 请求头；未配置或为空时，在发送请求前报错。不要将真实凭据写入源码、镜像或发布包。

安装到运行业务脚本的 Python 环境后，可直接使用：

```python
from ennew_harness import context, gui

current = context.get_current_context()
gui.send("file_changed", {"file": "report.md"})
```

上述无参数读取上下文和 `gui.send` 都从运行时的 `CODEX_THREAD_ID` 获取当前线程身份。`gui.send` 要求传入非空的 `type` 和字典 `payload`，把 `type` 同时写入 `params.type` 与 `params.message` 中的业务 JSON，经 Worker 本机 `127.0.0.1:18080/internal/events` 发到当前线程的前端连接。只有线程正在执行且前端连接仍在时才能发送；接口返回成功表示消息已写入 WebSocket，不保证前端已处理。

MCP 回调中传入宿主提供的本次请求 `ctx`，SDK 从 `ctx.meta["threadId"]` 获取线程身份，不读取或修改 `CODEX_THREAD_ID`。元数据缺失或线程 ID 不是非空字符串时，在发送请求前报错，不回退环境变量。线程身份不要从模型填写的工具参数中获取。此方式不要求 SDK 安装 MCP 依赖，也不支持在尚无请求上下文的 MCP 启动阶段获取线程身份。

在异步 MCP 回调中，使用以下方式避免同步网关请求阻塞事件循环：

```python
import asyncio
from ennew_harness import context

current = await asyncio.to_thread(context.get_current_context, ctx)
```

`context.get_current_context()` 优先读取系统环境变量 `ENV` 并转为大写；`ENV` 未设置或为空字符串时，再读取 `HARNESS_ENV`（保持原有大小写要求）。取到的值必须是 `FAT`、`UAT` 或 `PROD`；非空但无效的 `ENV` 会直接报错，不会回退。SDK 根据该值选择网关配置，并完整返回网关响应中的 `data`，包括 `authTokens`、`businessContext` 及后续新增字段。返回值可能包含敏感凭据，业务脚本不得记录、展示或转发完整上下文。三套网关 URL 定义在 `ennew_harness/context.py`，请求不内置 Token。安装 SDK 不会自动授予业务网关访问权限。

源码仓库中可运行上下文示例脚本：`python3 fat_context.py`。该脚本不随安装包提供。
