cosens-sdk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,15 @@
1
+ .DS_Store
2
+ .env
3
+ .env.*
4
+ !.env.example
5
+ .venv/
6
+ __pycache__/
7
+ .pytest_cache/
8
+ *.pyc
9
+ *.sqlite3
10
+ *.sqlite3-*
11
+ *.egg-info/
12
+ dist/
13
+ build/
14
+ typescript/node_modules/
15
+ python/docs/testing/latest-cn/
@@ -0,0 +1,246 @@
1
+ Metadata-Version: 2.5
2
+ Name: cosens-sdk
3
+ Version: 0.1.0
4
+ Summary: CoSens Python SDK for OpenAI and RSI workflows
5
+ Requires-Python: >=3.10
6
+ Requires-Dist: httpx<1,>=0.27
7
+ Requires-Dist: openai<2.55,>=2.54
8
+ Provides-Extra: agents
9
+ Requires-Dist: openai-agents<0.21,>=0.20; extra == 'agents'
10
+ Provides-Extra: examples
11
+ Requires-Dist: openai-agents<0.21,>=0.20; extra == 'examples'
12
+ Requires-Dist: python-dotenv<2,>=1; extra == 'examples'
13
+ Provides-Extra: test
14
+ Requires-Dist: build>=1; extra == 'test'
15
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'test'
16
+ Requires-Dist: pytest>=8; extra == 'test'
17
+ Description-Content-Type: text/markdown
18
+
19
+ # CoSens Python SDK
20
+
21
+ 在现有 OpenAI 应用中加入 Recipe、Memory 召回,以及 RSI 任务消息与结果上报。业务任务由你的 OpenAI 客户端或 Agents SDK 执行,CoSens 负责上下文与经验流程。
22
+
23
+ [安装](#安装) · [配置](#配置) · [快速开始](#快速开始) · [三种可运行示例](#三种可运行示例) · [常见问题](#常见问题) · [API 参考](docs/api-reference.md)
24
+
25
+ 新增任务工作流的 Python / TypeScript 原子方法与恢复约束见[开发契约](docs/2026-10-28-task-workflow-sdk-design.md)。本页的透明包装及显式 Run 示例仍使用旧 `/v1/runs` 协议。
26
+
27
+ 新版 Memory 与 guided Run 原子方法已加入 `client.atoms` 和 `client.sync_atoms`:来源版本写入、Memory 列表、guided 取下一步/提交步骤/完成及事件读取。方法参数见 [API 参考](docs/api-reference.md)。2026-10-29 固定 CN 区域后,Recipe、Memory 召回/列表、来源版本更新、guided Run 完整步骤流及 Task → Execution → Revision 冒烟测试通过,见 [验证记录](docs/testing/2026-10-29-v3-cn-contract.json)。Memory 抽取作业仍 pending;文档上传的四个原子方法已实现并完成离线测试,使用方式见 [API 参考](docs/api-reference.md#文档上传);一次性上传的 grant 路由尚未出现在 CN OpenAPI 中,真实联调待下游部署。
28
+
29
+ 在 IDEA 中选择 `00_all_tests_CN` 可运行两种语言的完整离线测试和 CN 网关检查;`00_all_tests_CN_live` 还会执行两种语言的真实模型示例。`04_task_workflow_CN` 单独检查新工作流。网关尚未部署新路由时,新工作流测试只读退出(代码 2);详见根目录 [测试说明](../README.md#开发与验证)。
30
+
31
+ ## 安装
32
+
33
+ 要求 **Python 3.10+**。当前支持 `openai` 2.54.x,Agent 接入使用 `openai-agents` 0.20.x。以下命令均从 **CoSens-SDK 仓库根目录**执行:
34
+
35
+ ```bash
36
+ python3 -m venv python/.venv
37
+ source python/.venv/bin/activate
38
+ python -m pip install -e "./python[examples]"
39
+ ```
40
+
41
+ Windows 激活命令为 `python\.venv\Scripts\activate`。`examples` 安装三个示例所需的 Agents SDK 和 dotenv。仅使用透明包装可安装 `python -m pip install ./python`;仅增加 Agent 支持可安装 `"./python[agents]"`。这里使用源码安装,不依赖同名 PyPI 包是否已发布。
42
+
43
+ ## 配置
44
+
45
+ 复制 [.env.example](.env.example) 为同目录的 `python/.env`,填写:
46
+
47
+ ```dotenv
48
+ OPENAI_API_KEY=your-openai-key
49
+ OPENAI_MODEL=your-model-name
50
+ RSI_API_KEY=your-friday-key
51
+ ```
52
+
53
+ | 配置项 | 用途 | 必填 |
54
+ | --- | --- | --- |
55
+ | `OPENAI_API_KEY` | OpenAI 或兼容模型服务的凭证 | 是 |
56
+ | `OPENAI_MODEL` | 你有权限调用的模型名,示例使用 Responses API | 是 |
57
+ | `RSI_API_KEY` | Friday 用户 Key,用于 CoSens 网关 | 是 |
58
+ | `OPENAI_BASE_URL` | 自定义兼容模型服务地址;不填使用 OpenAI 默认地址 | 否 |
59
+ | `COSENS_MODE` | 透明示例的模式,默认 `auto`,可改为 `disable` | 否 |
60
+ | `COSENS_INPUT` | 示例任务文字,不填使用内置集成测试问题 | 否 |
61
+ | `COSENS_REGION` | CoSens 服务区域,`cn`(默认)或 `us` | 否 |
62
+ | `RSI_API_KEY_CN` / `RSI_API_KEY_US` | 示例按区域选用的 Friday Key;未配置时使用 `RSI_API_KEY` | 否 |
63
+
64
+ 三个示例自动读取 `python/.env`,已有进程环境变量优先。**SDK 本身不自动读取 `.env`**;你自己的应用可使用环境变量或 `load_dotenv()`。
65
+
66
+ CoSens 网关由 SDK 内部按 `COSENS_REGION` 选择:国内 `cn` 为 `https://friday-rsi-cn.stardust-ai.com/api`,美国 `us` 为 `https://rsi.cosens.ai/api`。无需传入 CoSens `base_url` 或 `X_User_Id`,用户身份由网关注入。`OPENAI_BASE_URL` 仅配置模型服务。
67
+
68
+ ### 国内区与美国区测试
69
+
70
+ 三个示例共用同一套代码,在 `python/.env` 中配置区域与对应 Key:
71
+
72
+ ```dotenv
73
+ COSENS_REGION=us
74
+ RSI_API_KEY_CN=your-cn-friday-key
75
+ RSI_API_KEY_US=your-us-friday-key
76
+ ```
77
+
78
+ 这些值是占位符,真实联调需要有效 Key。示例优先使用对应区域的 Key,未设置或为空时回退到 `RSI_API_KEY`;显式填了占位符则在发送任何请求前提示补全配置,不会回退。不要假设两区 Key 通用。这个 Key 选择逻辑属于示例辅助代码;应用直接使用 SDK 时仍通过 `api_key` 或 `RSI_API_KEY` / `COSENS_API_KEY` 提供当前区域凭证。
79
+
80
+ IDEA 本地运行配置 `01_transparent`、`02_explicit_run`、`03_atomic` 固定测试国内区;同名加 `_US` 的三个入口测试美国区。也可直接打开示例运行,此时使用 `.env` 中的区域。终端临时切换示例:
81
+
82
+ ```bash
83
+ COSENS_REGION=us python/.venv/bin/python python/examples/01_transparent.py
84
+ COSENS_REGION=us python/.venv/bin/python python/examples/02_explicit_run.py
85
+ COSENS_REGION=us python/.venv/bin/python python/examples/03_atomic.py
86
+ ```
87
+
88
+ 客户端在初始化时固定区域,切换区域需新建客户端。两区的 Run 恢复状态和消息确认游标相互隔离;国内区已有状态继续可用。
89
+
90
+ 每个 CoSens 服务端请求携带 `X-Auth-Type: api_key` 和 `Authorization: Bearer <api_key>`。Friday Key 经 HTTPS 发送,证书验证保持开启,不跟随重定向;这两个头不会加到原生 OpenAI 模型请求。请使用环境变量或部署平台密钥管理;`.env` 已被 Git 忽略。不要把真实 Key 写入提交到仓库的源码。
91
+
92
+ ## 快速开始
93
+
94
+ ```python
95
+ import os
96
+ from openai import OpenAI
97
+ from cosens import cosens
98
+
99
+ native = OpenAI()
100
+ client = cosens(native, api_key=os.environ["RSI_API_KEY"], mode="auto")
101
+ try:
102
+ response = client.responses.create(
103
+ model=os.environ["OPENAI_MODEL"],
104
+ input="请帮我总结这次任务中可以复用的经验。",
105
+ )
106
+ print(response.output_text)
107
+ finally:
108
+ client.close()
109
+ ```
110
+
111
+ 接入只需 `native`、`api_key`、`mode`。SDK 默认复用业务请求的模型做提交判断,无需额外填写 `decision_model` 或 `session`。Friday Key 也可省略参数从环境读取,优先级为显式 `api_key` → `RSI_API_KEY` → `COSENS_API_KEY`。
112
+
113
+ ## 三种可运行示例
114
+
115
+ 在 PyCharm / IntelliJ Python 插件 / VS Code 中,把解释器选为本项目的 **`python/.venv/bin/python`**(Windows 为 `python\.venv\Scripts\python.exe`)。完成 `.env` 配置后,打开对应文件点击 **Run Python File / Run**。也可从仓库根目录运行下列命令。
116
+
117
+ ### 1. 透明包装 OpenAI
118
+
119
+ **[打开 01_transparent.py](examples/01_transparent.py)**
120
+
121
+ ```bash
122
+ python python/examples/01_transparent.py
123
+ ```
124
+
125
+ 核心调用仍为原生 OpenAI 形式,不显式调用 CoSens `run()`:
126
+
127
+ ```python
128
+ client = cosens(native, api_key=friday_key, mode="auto")
129
+ response = client.responses.create(model=model, input=user_input)
130
+ print(response.output_text)
131
+ ```
132
+
133
+ `auto` 先用模型判断是否需要 RSI Run;命中则准备 Run、获取冻结上下文,再执行业务模型、上报消息和提交结果。不命中或分类失败时,通过公开 Recipe + Memory 接口召回,不创建 Run。`disable` 跳过自动判断和自动 Run,但仍然召回。
134
+
135
+ 运行会输出答案、capture、turn_id、run_id 和本地 state。**auto 没有创建 Run 是合法结果**;不要将 `run_id: None` 直接视为失败。`auto` 的决策请求增加一次模型调用,模型服务需支持 Responses 结构化输出。高级参数 `decision_model` 可覆盖默认选择。
136
+
137
+ ### 2. 显式调用 run
138
+
139
+ **[打开 02_explicit_run.py](examples/02_explicit_run.py)**
140
+
141
+ ```bash
142
+ python python/examples/02_explicit_run.py
143
+ ```
144
+
145
+ ```python
146
+ agent = Agent(name="assistant", model=model, tools=[])
147
+ client = cosens(agent, api_key=friday_key, mode="disable")
148
+ result = await client.run(agent, user_input, session=session)
149
+ print(result.final_output)
150
+ ```
151
+
152
+ 完整文件使用 `OpenAIResponsesModel` 绑定真实 `AsyncOpenAI`,因此你配置的模型 Key 和模型地址会被实际使用。`disable` 关闭自动触发,显式 `run()` 仍组合原子步骤完成 RSI 流程;不会再调用分类模型。
153
+
154
+ 示例使用 Agents SDK 的 `SQLiteSession` 保存聊天历史,数据库位于 `~/.cosens/example-sessions.sqlite3`,控制台打印 session_id。每次点击生成一个新会话;连续聊天应复用同一个 Session。历史中已获得 `durable_ack` 的事件不重复上报。示例关闭 Agents tracing,避免额外发送 tracing 数据;可按应用需要自行开启。
155
+
156
+ ### 3. 直接编排原子接口
157
+
158
+ **[打开 03_atomic.py](examples/03_atomic.py)**
159
+
160
+ ```bash
161
+ python python/examples/03_atomic.py
162
+ ```
163
+
164
+ 完整文件展开以下主要流程:
165
+
166
+ ```text
167
+ 上传输入 artifact
168
+ → prepare(processing 时以同一 key 有界轮询)
169
+ → get_run,冻结 Recipe / Context / Snapshot
170
+ → session_events,确认用户消息 ACK
171
+ → 应用调用真实 OpenAI 模型,使用冻结上下文
172
+ → session_events,确认助手回复 ACK
173
+ → 上传输出 artifact → submit → get_trace
174
+ ```
175
+
176
+ 这里不调用包装器 `run()`,应用自己组织原子方法。服务端召回发生在模型调用前,工具循环应复用冻结结果。示例是单任务演示:每次运行生成新的 key;打印的 key、run_id 和实际输出须用于失败后的对账,不能直接重跑代替恢复。
177
+
178
+ 有决策分支的任务可加入 `guidance` / `checkpoint`;只有拿到真实反馈后才调用 `feedback` / `improve`,发布需显式调用管理员原子接口。完整方法与调用时机见 [API 参考](docs/api-reference.md)。生产应用还需持久化原子流程自身的任务状态和 ACK 游标。
179
+
180
+ ## 模式与兼容性
181
+
182
+ | 入口 / 模式 | 模型调用前召回 | 创建 RSI Run | 执行者 |
183
+ | --- | --- | --- | --- |
184
+ | 透明 `auto` | 每 turn 一次 | 由模型判断 | 原始 OpenAI client |
185
+ | 透明 `disable` | 每 turn 一次 | 不自动创建 | 原始 OpenAI client |
186
+ | 显式 `run()` + `disable` | 每 turn 一次 | 显式创建 | OpenAI Agents SDK |
187
+ | 原子接口 | 由应用在模型前调用 | 应用显式 prepare | 应用自己的模型/工具代码 |
188
+
189
+ 当前透明 `approval` 协调器契约未确认,命中审批流程会明确报错;不要用于这些示例。
190
+
191
+ 同步 `OpenAI`、异步 `AsyncOpenAI` 均可包装。对话生成适配 Responses / Chat Completions 的 create、parse、stream;文件、向量库等其他资源方法透传,原生返回值保持原形。`with_options()` / `copy()` 仍返回包装对象。对于无法安全捕获的生成请求,SDK 保留原生调用,设置 `rsi_capture="unsupported"`,此时不保证 RSI 召回与上报。直接调用 `client.native` 会绕过包装。
192
+
193
+ ## Session 与故障恢复
194
+
195
+ 不传 Session 的透明调用只能捕获本次请求可见的消息,无法读取应用未提供的旧聊天。外部历史、稳定 turn 边界和工具循环的进阶接入见 [Session 说明](docs/api-reference.md#session工具和恢复)。
196
+
197
+ CoSens 默认把状态和 ACK 游标写入 `~/.cosens/state.sqlite3`,可用高级参数 `state_path` 指定。记录按服务及凭证摘要隔离;部署时应持久化该文件。只有远端 ACK 确认后才推进消息游标,丢失本地状态后不能保证跨 Run 全局去重。
198
+
199
+ ```python
200
+ turn_id = client.cosens.last_turn_id
201
+ state = client.cosens.get_turn(turn_id)
202
+ ```
203
+
204
+ 如果模型结果已经返回,但 state 为 `completion_pending`,不要直接重新执行模型或工具。保留原 Session、状态文件和 turn_id,透明同步客户端使用 `client.cosens.reconcile(turn_id)` 对账,异步 OpenAI 客户端使用 `await`。显式 Agent 示例把 Session 传给了 `run()`,恢复时也必须传入同一个 Session:
205
+
206
+ ```python
207
+ # 重启后用控制台记录的原 session_id 和同一数据库重新创建 SQLiteSession。
208
+ await client.cosens.reconcile(turn_id, session=session)
209
+ ```
210
+
211
+ 原生执行结果不明或抛出 `RSIRecoveryRequired` 时,需要应用先核实实际执行情况。详见 [恢复边界](docs/api-reference.md#恢复与服务端边界)。
212
+
213
+ ## 常见问题
214
+
215
+ | 现象 | 处理方式 |
216
+ | --- | --- |
217
+ | `ModuleNotFoundError: cosens / agents / dotenv` | 确认 IDE 使用安装过 `./python[examples]` 的解释器 |
218
+ | 提示缺少配置 | 将 `.env.example` 复制到 `python/.env`,填写三个必填值;检查 IDE 环境变量是否覆盖它 |
219
+ | 模型 401 / 403 / 404 | 核对 OpenAI Key、模型访问权限、模型名与模型服务地址 |
220
+ | 网关 401 / 403 | 核对 Friday 用户 Key 及网关权限,无需自己填写 X_User_Id |
221
+ | 召回失败、未调用业务模型 | 检查网关连通性与返回契约;SDK 不把错误静默当成空召回 |
222
+ | 模型有答案、RSI 未完成 | 保存 turn_id / run_id,按恢复流程处理,避免重复执行 |
223
+ | 想验证每次都创建 Run | 运行显式 run 或原子示例;auto 的创建与否由模型决策 |
224
+
225
+ 示例错误只输出类型、HTTP 状态和 request_id,不输出远端错误正文。请结合上述信息和服务端日志定位。
226
+
227
+ ## 开发与测试
228
+
229
+ ```bash
230
+ python -m pip install -e "./python[examples,test]"
231
+ python -m pytest python/tests
232
+ python -m build python
233
+ ```
234
+
235
+ `tests/test_runnable_examples.py` 从不同工作目录执行三个脚本,使用真实 OpenAI SDK、真实 Agents Runner 和本地状态存储,仅模拟 HTTP 服务,验证召回顺序、上下文注入、消息上报和凭证隔离。它不会消耗真实模型额度。
236
+
237
+ `examples/validate_gateway.py` 与 `examples/validate_wrapped_gateway.py` 是独立网关联调脚本,后者使用本地模型替身;它们与上述真实模型示例用途不同。复现方式、已验证范围见 [网关联调报告](docs/2026-10-27-gateway-validation.md) 和 [API 参考](docs/api-reference.md#复现网关联调)。
238
+
239
+ ## 进一步阅读
240
+
241
+ - [设计文档与每步调用时机](docs/2026-10-26-cosens-python-sdk-design.md)
242
+ - [原子 API 与恢复边界](docs/api-reference.md)
243
+ - [OpenAI Python SDK](https://github.com/openai/openai-python)
244
+ - [OpenAI Agents SDK](https://github.com/openai/openai-agents-python)
245
+
246
+ 新增 30 个请求边界回归测试(Python / TypeScript 各 15 个),已纳入现有测试入口;用例清单、单独运行命令、缺陷修复与最新验证结果见[测试说明](docs/testing/2026-10-29-sdk-request-regression.md)。
@@ -0,0 +1,228 @@
1
+ # CoSens Python SDK
2
+
3
+ 在现有 OpenAI 应用中加入 Recipe、Memory 召回,以及 RSI 任务消息与结果上报。业务任务由你的 OpenAI 客户端或 Agents SDK 执行,CoSens 负责上下文与经验流程。
4
+
5
+ [安装](#安装) · [配置](#配置) · [快速开始](#快速开始) · [三种可运行示例](#三种可运行示例) · [常见问题](#常见问题) · [API 参考](docs/api-reference.md)
6
+
7
+ 新增任务工作流的 Python / TypeScript 原子方法与恢复约束见[开发契约](docs/2026-10-28-task-workflow-sdk-design.md)。本页的透明包装及显式 Run 示例仍使用旧 `/v1/runs` 协议。
8
+
9
+ 新版 Memory 与 guided Run 原子方法已加入 `client.atoms` 和 `client.sync_atoms`:来源版本写入、Memory 列表、guided 取下一步/提交步骤/完成及事件读取。方法参数见 [API 参考](docs/api-reference.md)。2026-10-29 固定 CN 区域后,Recipe、Memory 召回/列表、来源版本更新、guided Run 完整步骤流及 Task → Execution → Revision 冒烟测试通过,见 [验证记录](docs/testing/2026-10-29-v3-cn-contract.json)。Memory 抽取作业仍 pending;文档上传的四个原子方法已实现并完成离线测试,使用方式见 [API 参考](docs/api-reference.md#文档上传);一次性上传的 grant 路由尚未出现在 CN OpenAPI 中,真实联调待下游部署。
10
+
11
+ 在 IDEA 中选择 `00_all_tests_CN` 可运行两种语言的完整离线测试和 CN 网关检查;`00_all_tests_CN_live` 还会执行两种语言的真实模型示例。`04_task_workflow_CN` 单独检查新工作流。网关尚未部署新路由时,新工作流测试只读退出(代码 2);详见根目录 [测试说明](../README.md#开发与验证)。
12
+
13
+ ## 安装
14
+
15
+ 要求 **Python 3.10+**。当前支持 `openai` 2.54.x,Agent 接入使用 `openai-agents` 0.20.x。以下命令均从 **CoSens-SDK 仓库根目录**执行:
16
+
17
+ ```bash
18
+ python3 -m venv python/.venv
19
+ source python/.venv/bin/activate
20
+ python -m pip install -e "./python[examples]"
21
+ ```
22
+
23
+ Windows 激活命令为 `python\.venv\Scripts\activate`。`examples` 安装三个示例所需的 Agents SDK 和 dotenv。仅使用透明包装可安装 `python -m pip install ./python`;仅增加 Agent 支持可安装 `"./python[agents]"`。这里使用源码安装,不依赖同名 PyPI 包是否已发布。
24
+
25
+ ## 配置
26
+
27
+ 复制 [.env.example](.env.example) 为同目录的 `python/.env`,填写:
28
+
29
+ ```dotenv
30
+ OPENAI_API_KEY=your-openai-key
31
+ OPENAI_MODEL=your-model-name
32
+ RSI_API_KEY=your-friday-key
33
+ ```
34
+
35
+ | 配置项 | 用途 | 必填 |
36
+ | --- | --- | --- |
37
+ | `OPENAI_API_KEY` | OpenAI 或兼容模型服务的凭证 | 是 |
38
+ | `OPENAI_MODEL` | 你有权限调用的模型名,示例使用 Responses API | 是 |
39
+ | `RSI_API_KEY` | Friday 用户 Key,用于 CoSens 网关 | 是 |
40
+ | `OPENAI_BASE_URL` | 自定义兼容模型服务地址;不填使用 OpenAI 默认地址 | 否 |
41
+ | `COSENS_MODE` | 透明示例的模式,默认 `auto`,可改为 `disable` | 否 |
42
+ | `COSENS_INPUT` | 示例任务文字,不填使用内置集成测试问题 | 否 |
43
+ | `COSENS_REGION` | CoSens 服务区域,`cn`(默认)或 `us` | 否 |
44
+ | `RSI_API_KEY_CN` / `RSI_API_KEY_US` | 示例按区域选用的 Friday Key;未配置时使用 `RSI_API_KEY` | 否 |
45
+
46
+ 三个示例自动读取 `python/.env`,已有进程环境变量优先。**SDK 本身不自动读取 `.env`**;你自己的应用可使用环境变量或 `load_dotenv()`。
47
+
48
+ CoSens 网关由 SDK 内部按 `COSENS_REGION` 选择:国内 `cn` 为 `https://friday-rsi-cn.stardust-ai.com/api`,美国 `us` 为 `https://rsi.cosens.ai/api`。无需传入 CoSens `base_url` 或 `X_User_Id`,用户身份由网关注入。`OPENAI_BASE_URL` 仅配置模型服务。
49
+
50
+ ### 国内区与美国区测试
51
+
52
+ 三个示例共用同一套代码,在 `python/.env` 中配置区域与对应 Key:
53
+
54
+ ```dotenv
55
+ COSENS_REGION=us
56
+ RSI_API_KEY_CN=your-cn-friday-key
57
+ RSI_API_KEY_US=your-us-friday-key
58
+ ```
59
+
60
+ 这些值是占位符,真实联调需要有效 Key。示例优先使用对应区域的 Key,未设置或为空时回退到 `RSI_API_KEY`;显式填了占位符则在发送任何请求前提示补全配置,不会回退。不要假设两区 Key 通用。这个 Key 选择逻辑属于示例辅助代码;应用直接使用 SDK 时仍通过 `api_key` 或 `RSI_API_KEY` / `COSENS_API_KEY` 提供当前区域凭证。
61
+
62
+ IDEA 本地运行配置 `01_transparent`、`02_explicit_run`、`03_atomic` 固定测试国内区;同名加 `_US` 的三个入口测试美国区。也可直接打开示例运行,此时使用 `.env` 中的区域。终端临时切换示例:
63
+
64
+ ```bash
65
+ COSENS_REGION=us python/.venv/bin/python python/examples/01_transparent.py
66
+ COSENS_REGION=us python/.venv/bin/python python/examples/02_explicit_run.py
67
+ COSENS_REGION=us python/.venv/bin/python python/examples/03_atomic.py
68
+ ```
69
+
70
+ 客户端在初始化时固定区域,切换区域需新建客户端。两区的 Run 恢复状态和消息确认游标相互隔离;国内区已有状态继续可用。
71
+
72
+ 每个 CoSens 服务端请求携带 `X-Auth-Type: api_key` 和 `Authorization: Bearer <api_key>`。Friday Key 经 HTTPS 发送,证书验证保持开启,不跟随重定向;这两个头不会加到原生 OpenAI 模型请求。请使用环境变量或部署平台密钥管理;`.env` 已被 Git 忽略。不要把真实 Key 写入提交到仓库的源码。
73
+
74
+ ## 快速开始
75
+
76
+ ```python
77
+ import os
78
+ from openai import OpenAI
79
+ from cosens import cosens
80
+
81
+ native = OpenAI()
82
+ client = cosens(native, api_key=os.environ["RSI_API_KEY"], mode="auto")
83
+ try:
84
+ response = client.responses.create(
85
+ model=os.environ["OPENAI_MODEL"],
86
+ input="请帮我总结这次任务中可以复用的经验。",
87
+ )
88
+ print(response.output_text)
89
+ finally:
90
+ client.close()
91
+ ```
92
+
93
+ 接入只需 `native`、`api_key`、`mode`。SDK 默认复用业务请求的模型做提交判断,无需额外填写 `decision_model` 或 `session`。Friday Key 也可省略参数从环境读取,优先级为显式 `api_key` → `RSI_API_KEY` → `COSENS_API_KEY`。
94
+
95
+ ## 三种可运行示例
96
+
97
+ 在 PyCharm / IntelliJ Python 插件 / VS Code 中,把解释器选为本项目的 **`python/.venv/bin/python`**(Windows 为 `python\.venv\Scripts\python.exe`)。完成 `.env` 配置后,打开对应文件点击 **Run Python File / Run**。也可从仓库根目录运行下列命令。
98
+
99
+ ### 1. 透明包装 OpenAI
100
+
101
+ **[打开 01_transparent.py](examples/01_transparent.py)**
102
+
103
+ ```bash
104
+ python python/examples/01_transparent.py
105
+ ```
106
+
107
+ 核心调用仍为原生 OpenAI 形式,不显式调用 CoSens `run()`:
108
+
109
+ ```python
110
+ client = cosens(native, api_key=friday_key, mode="auto")
111
+ response = client.responses.create(model=model, input=user_input)
112
+ print(response.output_text)
113
+ ```
114
+
115
+ `auto` 先用模型判断是否需要 RSI Run;命中则准备 Run、获取冻结上下文,再执行业务模型、上报消息和提交结果。不命中或分类失败时,通过公开 Recipe + Memory 接口召回,不创建 Run。`disable` 跳过自动判断和自动 Run,但仍然召回。
116
+
117
+ 运行会输出答案、capture、turn_id、run_id 和本地 state。**auto 没有创建 Run 是合法结果**;不要将 `run_id: None` 直接视为失败。`auto` 的决策请求增加一次模型调用,模型服务需支持 Responses 结构化输出。高级参数 `decision_model` 可覆盖默认选择。
118
+
119
+ ### 2. 显式调用 run
120
+
121
+ **[打开 02_explicit_run.py](examples/02_explicit_run.py)**
122
+
123
+ ```bash
124
+ python python/examples/02_explicit_run.py
125
+ ```
126
+
127
+ ```python
128
+ agent = Agent(name="assistant", model=model, tools=[])
129
+ client = cosens(agent, api_key=friday_key, mode="disable")
130
+ result = await client.run(agent, user_input, session=session)
131
+ print(result.final_output)
132
+ ```
133
+
134
+ 完整文件使用 `OpenAIResponsesModel` 绑定真实 `AsyncOpenAI`,因此你配置的模型 Key 和模型地址会被实际使用。`disable` 关闭自动触发,显式 `run()` 仍组合原子步骤完成 RSI 流程;不会再调用分类模型。
135
+
136
+ 示例使用 Agents SDK 的 `SQLiteSession` 保存聊天历史,数据库位于 `~/.cosens/example-sessions.sqlite3`,控制台打印 session_id。每次点击生成一个新会话;连续聊天应复用同一个 Session。历史中已获得 `durable_ack` 的事件不重复上报。示例关闭 Agents tracing,避免额外发送 tracing 数据;可按应用需要自行开启。
137
+
138
+ ### 3. 直接编排原子接口
139
+
140
+ **[打开 03_atomic.py](examples/03_atomic.py)**
141
+
142
+ ```bash
143
+ python python/examples/03_atomic.py
144
+ ```
145
+
146
+ 完整文件展开以下主要流程:
147
+
148
+ ```text
149
+ 上传输入 artifact
150
+ → prepare(processing 时以同一 key 有界轮询)
151
+ → get_run,冻结 Recipe / Context / Snapshot
152
+ → session_events,确认用户消息 ACK
153
+ → 应用调用真实 OpenAI 模型,使用冻结上下文
154
+ → session_events,确认助手回复 ACK
155
+ → 上传输出 artifact → submit → get_trace
156
+ ```
157
+
158
+ 这里不调用包装器 `run()`,应用自己组织原子方法。服务端召回发生在模型调用前,工具循环应复用冻结结果。示例是单任务演示:每次运行生成新的 key;打印的 key、run_id 和实际输出须用于失败后的对账,不能直接重跑代替恢复。
159
+
160
+ 有决策分支的任务可加入 `guidance` / `checkpoint`;只有拿到真实反馈后才调用 `feedback` / `improve`,发布需显式调用管理员原子接口。完整方法与调用时机见 [API 参考](docs/api-reference.md)。生产应用还需持久化原子流程自身的任务状态和 ACK 游标。
161
+
162
+ ## 模式与兼容性
163
+
164
+ | 入口 / 模式 | 模型调用前召回 | 创建 RSI Run | 执行者 |
165
+ | --- | --- | --- | --- |
166
+ | 透明 `auto` | 每 turn 一次 | 由模型判断 | 原始 OpenAI client |
167
+ | 透明 `disable` | 每 turn 一次 | 不自动创建 | 原始 OpenAI client |
168
+ | 显式 `run()` + `disable` | 每 turn 一次 | 显式创建 | OpenAI Agents SDK |
169
+ | 原子接口 | 由应用在模型前调用 | 应用显式 prepare | 应用自己的模型/工具代码 |
170
+
171
+ 当前透明 `approval` 协调器契约未确认,命中审批流程会明确报错;不要用于这些示例。
172
+
173
+ 同步 `OpenAI`、异步 `AsyncOpenAI` 均可包装。对话生成适配 Responses / Chat Completions 的 create、parse、stream;文件、向量库等其他资源方法透传,原生返回值保持原形。`with_options()` / `copy()` 仍返回包装对象。对于无法安全捕获的生成请求,SDK 保留原生调用,设置 `rsi_capture="unsupported"`,此时不保证 RSI 召回与上报。直接调用 `client.native` 会绕过包装。
174
+
175
+ ## Session 与故障恢复
176
+
177
+ 不传 Session 的透明调用只能捕获本次请求可见的消息,无法读取应用未提供的旧聊天。外部历史、稳定 turn 边界和工具循环的进阶接入见 [Session 说明](docs/api-reference.md#session工具和恢复)。
178
+
179
+ CoSens 默认把状态和 ACK 游标写入 `~/.cosens/state.sqlite3`,可用高级参数 `state_path` 指定。记录按服务及凭证摘要隔离;部署时应持久化该文件。只有远端 ACK 确认后才推进消息游标,丢失本地状态后不能保证跨 Run 全局去重。
180
+
181
+ ```python
182
+ turn_id = client.cosens.last_turn_id
183
+ state = client.cosens.get_turn(turn_id)
184
+ ```
185
+
186
+ 如果模型结果已经返回,但 state 为 `completion_pending`,不要直接重新执行模型或工具。保留原 Session、状态文件和 turn_id,透明同步客户端使用 `client.cosens.reconcile(turn_id)` 对账,异步 OpenAI 客户端使用 `await`。显式 Agent 示例把 Session 传给了 `run()`,恢复时也必须传入同一个 Session:
187
+
188
+ ```python
189
+ # 重启后用控制台记录的原 session_id 和同一数据库重新创建 SQLiteSession。
190
+ await client.cosens.reconcile(turn_id, session=session)
191
+ ```
192
+
193
+ 原生执行结果不明或抛出 `RSIRecoveryRequired` 时,需要应用先核实实际执行情况。详见 [恢复边界](docs/api-reference.md#恢复与服务端边界)。
194
+
195
+ ## 常见问题
196
+
197
+ | 现象 | 处理方式 |
198
+ | --- | --- |
199
+ | `ModuleNotFoundError: cosens / agents / dotenv` | 确认 IDE 使用安装过 `./python[examples]` 的解释器 |
200
+ | 提示缺少配置 | 将 `.env.example` 复制到 `python/.env`,填写三个必填值;检查 IDE 环境变量是否覆盖它 |
201
+ | 模型 401 / 403 / 404 | 核对 OpenAI Key、模型访问权限、模型名与模型服务地址 |
202
+ | 网关 401 / 403 | 核对 Friday 用户 Key 及网关权限,无需自己填写 X_User_Id |
203
+ | 召回失败、未调用业务模型 | 检查网关连通性与返回契约;SDK 不把错误静默当成空召回 |
204
+ | 模型有答案、RSI 未完成 | 保存 turn_id / run_id,按恢复流程处理,避免重复执行 |
205
+ | 想验证每次都创建 Run | 运行显式 run 或原子示例;auto 的创建与否由模型决策 |
206
+
207
+ 示例错误只输出类型、HTTP 状态和 request_id,不输出远端错误正文。请结合上述信息和服务端日志定位。
208
+
209
+ ## 开发与测试
210
+
211
+ ```bash
212
+ python -m pip install -e "./python[examples,test]"
213
+ python -m pytest python/tests
214
+ python -m build python
215
+ ```
216
+
217
+ `tests/test_runnable_examples.py` 从不同工作目录执行三个脚本,使用真实 OpenAI SDK、真实 Agents Runner 和本地状态存储,仅模拟 HTTP 服务,验证召回顺序、上下文注入、消息上报和凭证隔离。它不会消耗真实模型额度。
218
+
219
+ `examples/validate_gateway.py` 与 `examples/validate_wrapped_gateway.py` 是独立网关联调脚本,后者使用本地模型替身;它们与上述真实模型示例用途不同。复现方式、已验证范围见 [网关联调报告](docs/2026-10-27-gateway-validation.md) 和 [API 参考](docs/api-reference.md#复现网关联调)。
220
+
221
+ ## 进一步阅读
222
+
223
+ - [设计文档与每步调用时机](docs/2026-10-26-cosens-python-sdk-design.md)
224
+ - [原子 API 与恢复边界](docs/api-reference.md)
225
+ - [OpenAI Python SDK](https://github.com/openai/openai-python)
226
+ - [OpenAI Agents SDK](https://github.com/openai/openai-agents-python)
227
+
228
+ 新增 30 个请求边界回归测试(Python / TypeScript 各 15 个),已纳入现有测试入口;用例清单、单独运行命令、缺陷修复与最新验证结果见[测试说明](docs/testing/2026-10-29-sdk-request-regression.md)。
@@ -0,0 +1,129 @@
1
+ # Python SDK 进阶与原子 API
2
+
3
+ 基础安装和可运行示例见 [接入文档](../README.md)。以下是可选能力,普通透明接入只需 `native`、`api_key`、`mode`。
4
+
5
+ ## 新任务工作流
6
+
7
+ `client.atoms` 和 `client.sync_atoms` 已增加 Task、Execution、Revision、Attribution、Recipe Candidate、Verification、Memory v3 与 guided Run 的原子方法。方法名、请求体、幂等键和恢复语义见[任务工作流 SDK 开发契约](2026-10-28-task-workflow-sdk-design.md)。下方分别列出旧 `/v1/runs`、Memory 与文档上传 API。
8
+
9
+ ## 原子编排入口
10
+
11
+ `CoSensClient(api_key=...)` 是异步上下文管理器,`rsi.atoms` 不会替应用执行模型或工具。
12
+
13
+ 所有 CoSens 原子接口(包括 `admin.atoms`)均发送 `X-Auth-Type: api_key` 与 `Authorization: Bearer <api_key>`;`Idempotency-Key` 仅在相应调用提供稳定幂等键时发送。显式提供的键必须为非空、最多 256 字符且不含控制字符;可选键传入空字符串会报错,不会静默省略。
14
+
15
+ | 方法 | 调用时机 | 网关 `/api` 后路径 |
16
+ | --- | --- | --- |
17
+ | `artifact(name=..., content=...)` | 有真实输入材料或输出文本时 | `POST /v1/artifacts` |
18
+ | `prepare(objective=..., key=...)` | 新任务,模型调用前;同任务重试复用 key | `POST /v1/runs/prepare` |
19
+ | `get_run(run_id)` | prepare 就绪后冻结 snapshot;或恢复对账 | `GET /v1/runs/{run_id}` |
20
+ | `session_events(run_id, events)` | 上报未 ACK 的事件;收到 durable_ack 才推进游标 | `POST /v1/runs/{run_id}/session-events` |
21
+ | `initial_inputs(run_id, artifact_ids)` | 补充实际初始材料 | `POST /v1/runs/{run_id}/initial-inputs` |
22
+ | `submit(run_id, data=..., key=...)` | 本地模型/工具完成后,提交实际输出 | `POST /v1/runs/{run_id}/submit` |
23
+ | `feedback(run_id, data=..., key=...)` | 有真实用户反馈或验收证据后 | `POST /v1/runs/{run_id}/feedback` |
24
+ | `improve(run_id, reason=..., key=...)` | 明确要求发起改进时 | `POST /v1/runs/{run_id}/improvements` |
25
+ | `get_improvement(job_id)` / `wait_improvement(job_id)` | 查询/有界轮询异步改进 | `GET /v1/improvements/{job_id}` |
26
+ | `resume_improvement(job_id)` | 确认任务可恢复后 | `POST /v1/improvements/{job_id}/resume` |
27
+ | `admin.atoms.publish(job_id, expected_revision=..., reason=...)` | 显式批准发布时,须由外部网关实施管理员授权 | `POST /internal/admin/v1/improvements/{job_id}/publish` |
28
+
29
+ `prepare` 返回 `processing` 时,使用同一个 key 有界轮询;只有 `ready` 才进入模型调用。不要将一次请求超时当成失败后创建新任务的依据。三种入口的详细接口时机见 [设计文档](2026-10-26-cosens-python-sdk-design.md)。
30
+
31
+ ## Session、工具和恢复
32
+
33
+ 透明方式的 `session` 为高级可选项:不传时捕获本次请求可见的用户文本、回复及已适配工具事件,不能读取应用未提供的历史。外部 Session 需提供稳定的 `session_id` 和 `get_items()`。建议模型调用前写入本次用户消息,保持稳定消息 ID;后写入的新 ID 无法证明与已合成事件相同。用 `client.cosens.scope(session_id="...", turn_id="...")` 显式划定一个逻辑 turn,工具循环复用它。
34
+
35
+ 显式 Agent 的 Session 交给 Agents SDK 管理;不传 Session 时会提交最终结果,但没有 Session 聊天事件可增量上报。可运行的 [显式示例](../examples/02_explicit_run.py) 使用持久化 `SQLiteSession`。恢复需使用原 session_id、Session 数据库和 CoSens 状态文件。
36
+
37
+ 原生 Agent 工具审批中断时不会提交最终结果。通过 `await client.pending_state(agent, turn_id)` 取得原生 `RunState`,按 Agents SDK `approve()`/`reject()` 后,调用 `await client.resume(agent, turn_id, native_state, session=session)` 继续。`input_artifacts=[{"name": "...", "content": "..."}]` 上传真实输入文本;`final_output` 含 `files` 列表时可上传实际输出文件。
38
+
39
+ ## 恢复与服务端边界
40
+
41
+ Session 事件只在收到 `durable_ack` 后推进本地游标。失败后可查 `client.cosens.get_turn(turn_id)`;原生执行已完成但提交回执不明时用 `client.cosens.reconcile(turn_id)` 对账(异步客户端使用 `await`),不重新执行模型或工具。Agent 若在 `run()` 中传入 Session,对账也须显式 `await client.cosens.reconcile(turn_id, session=session)`;重启后先恢复原 session_id 和 Session 数据库,否则无法补报未 ACK 的历史。原生执行结果不明时抛 `RSIRecoveryRequired`,由宿主确认实际执行情况。透明调用的重试及工具续接必须保持 turn 创建时的 `mode`;模式变化或旧记录缺少模式时,SDK 会在模型调用和远端写入前拒绝隐式恢复。请持久化 `state_path`;丢失本地状态后,当前服务端不能保证跨 Run 的消息全局去重。
42
+
43
+ 网关 OpenAPI 当前标识为 1.0.0;以本次 curl 附件、网关实际返回和联调报告为准。审批协调器 `/v1/invocations` 仍未确认,透明 `approval` 命中时保持明确报错。单元测试使用模拟 HTTP;真实网关联调使用独立测试标识并写入合成测试数据,模型执行用本地替身验证编排,未调用真实模型或银行系统。详细时机与限制见 [设计文档](2026-10-26-cosens-python-sdk-design.md)。
44
+
45
+ ## Recipe、Memory 与决策接口
46
+
47
+ 普通原子接口(`atoms` 异步,`sync_atoms` 提供新增接口的同步形式):
48
+
49
+ | SDK 方法 | 网关 `/api` 后的路径 |
50
+ | --- | --- |
51
+ | `get_active_recipe(task_family=...)` | `GET /v1/recipes/active?task_family=...` |
52
+ | `memory_ingest(content=..., request_key=..., source_id=..., expected_revision=..., source_kind=..., durable=...)` | `POST /v1/memory/ingest` |
53
+ | `memory_recall(query=..., token_budget=1000)` | `POST /v1/memory/recall`;预算 1–8000 |
54
+ | `get_memory_items(limit=200)` | `GET /v1/memory/items?limit=...`;limit 1–500 |
55
+ | `get_memory_job(job_id)` | `GET /v1/memory/jobs/{job_id}` |
56
+ | `get_memory_experience(experience_id, revision=...)` | `GET /v1/memory/experiences/{experience_id}` |
57
+ | `get_memory()` | `GET /v1/memory` |
58
+ | `get_recipe_step(run_id, node_id)` | `GET /v1/runs/{run_id}/recipe/steps/{node_id}` |
59
+ | `guidance(run_id, data=...)` | `POST /v1/runs/{run_id}/guidance` |
60
+ | `checkpoint(run_id, data=...)` | `POST /v1/runs/{run_id}/checkpoint` |
61
+ | `get_decision(run_id, decision_id)` | `GET /v1/runs/{run_id}/decisions/{decision_id}` |
62
+ | `get_trace(run_id)` | `GET /v1/runs/{run_id}/trace` |
63
+ | `next_step(run_id)` | `POST /v1/runs/{run_id}/steps/next` |
64
+ | `submit_step(run_id, attempt_id, attempt_token=..., outputs=..., decision_id=..., actual_action_id=...)` | `POST /v1/runs/{run_id}/steps/{attempt_id}/submit` |
65
+ | `complete_guided(run_id)` | `POST /v1/runs/{run_id}/complete` |
66
+ | `get_events(run_id)` | `GET /v1/runs/{run_id}/events` |
67
+
68
+ `memory_ingest` 为兼容既有调用,SDK 仍显式发送 `source_kind="decision"`、`durable=True`;原始服务省略字段时的默认值分别是 `message`、`false`。需要原始服务默认语义时显式传 `source_kind="message", durable=False`。新增来源可省略 `expected_revision`(服务默认 0);更新来源时传入 `source_id` 和当前 revision。`memory_ingest` 返回 `pending` 时使用原 `job_id` 查询至 `committed` 或 `failed`。`prepare(..., execution_mode="guided")` 启用 guided;`managed` 被客户端拒绝。guided 步骤的 `attempt_id`/`attempt_token` 应持久保存;原生动作结果未知时先对账,不能重放动作。`get_events` 与 `get_trace` 是不同接口,`complete_guided` 不代替 assist 的 `submit`。
69
+
70
+ CN 已验证:`next_step` 的 `step_ready` 回执在 `node.output_contract` 声明输出端口。artifact 端口应传 `outputs={"files": [{"artifact_id": ..., "name": ..., "content_hash": ...}]}`,引用上传回执;单独 ID 不满足该端口。`submit_step` 的 HTTP 200 仍可能返回 `repair_required`,只有 `step_passed` 表示步骤通过。全流程完成后 `complete_guided` 返回 `completed`;`get_events` 返回含 `items` 列表的对象。
71
+
72
+ `admin.atoms` 新增显式调用:`bootstrap_bundle`、`evaluate_decision`、`evaluate_recipe`,对应附件的 Recipe 注册、决策评估、Recipe 评估接口。它们不会由透明包装自动触发;调用者须提交实际执行和评估证据。`feedback` 不等于经验已经 verified,异步写入需轮询 Job/经验版本确认。
73
+
74
+ `recall_context` 顺序读取 Recipe 和 Memory 后冻结本地结果,服务端未承诺两个独立读取拥有同一个事务快照。`disable` 使用 `general` 任务族;`auto` 未命中时使用分类结果的任务族。Recipe `not_found` 或 Memory 空列表是合法结果,HTTP 错误和缺失字段仍阻止业务模型调用。
75
+
76
+ ## 复现网关联调
77
+
78
+ 先由运行环境注入 `RSI_API_KEY`(没有设置时脚本隐藏输入 Key),在仓库根目录运行:
79
+
80
+ 两个诊断脚本均支持 `COSENS_REGION=cn`(默认)或 `us`,网关分别为 `https://friday-rsi-cn.stardust-ai.com/api`、`https://rsi.cosens.ai/api`。它们不加载 `.env` 或选择 `RSI_API_KEY_US`;请将目标区域的 Key 注入进程的 `RSI_API_KEY`。三种可直接运行的模型示例会读取 `.env` 并选择区域 Key,详见 [区域配置](../README.md#国内区与美国区测试)。
81
+
82
+ ```bash
83
+ # 只读验证:健康状态和无 Run 召回
84
+ python python/examples/validate_gateway.py --output /tmp/cosens-readonly.json
85
+
86
+ # 会写入合成 Recipe、Memory、Run 和评估记录
87
+ python python/examples/validate_gateway.py --write \
88
+ --transcript /path/to/FULL_CURL_TRANSCRIPT.md --output /tmp/cosens-workflow.json
89
+
90
+ # 真实网关 + 本地模型/Agent 替身;会创建测试 Run,需要 agents 可选依赖
91
+ python python/examples/validate_wrapped_gateway.py --output /tmp/cosens-wrapped.json
92
+ ```
93
+
94
+ ## 文档上传
95
+
96
+ Python 异步 `client.atoms` 和同步 `client.sync_atoms` 均支持以下四个方法:
97
+
98
+ | 方法 | 请求 |
99
+ | --- | --- |
100
+ | `create_document_upload_grant(filename=..., mime_type=..., **metadata)` | 签发一次性上传 grant |
101
+ | `upload_document_to_grant(grant, content=...)` | 将非空原始字节上传一次 |
102
+ | `upload_document(filename=..., mime_type=..., content=..., **metadata)` | 普通 multipart 上传 |
103
+ | `get_document_status(document_ids)` | 查询非空文档 ID 列表 |
104
+
105
+ ```python
106
+ import asyncio
107
+ import os
108
+ from pathlib import Path
109
+ from cosens import CoSensClient
110
+
111
+ async def main():
112
+ os.environ["COSENS_REGION"] = "cn"
113
+ async with CoSensClient(api_key=os.environ["RSI_API_KEY"]) as client:
114
+ content = Path("notes.txt").read_bytes()
115
+ grant = await client.atoms.create_document_upload_grant(
116
+ filename="notes.txt", mime_type="text/plain", wait_for_processing=False,
117
+ )
118
+ receipt = await client.atoms.upload_document_to_grant(grant, content=content)
119
+ # 持久化回执并检查业务状态;HTTP 200 不等于文件已完成处理。
120
+ if receipt.get("document_id"):
121
+ status = await client.atoms.get_document_status([receipt["document_id"]])
122
+ print(status)
123
+
124
+ asyncio.run(main())
125
+ ```
126
+
127
+ 普通 multipart 可单独使用 `await client.atoms.upload_document(filename="notes.txt", mime_type="text/plain", content=content)`;它与 grant 上传是两种入口,不应对同一结果不明的文件依次尝试。同步宿主改用 `client.sync_atoms` 并去掉方法调用的 `await`。
128
+
129
+ 元数据、URL 校验和恢复规则见[开发契约第 8.4 节](2026-10-28-task-workflow-sdk-design.md#84-文档上传)。SDK 不接受用户身份覆盖,不自动重试一次性令牌,也不执行 grant 内的命令文本。Key 来自构造参数或进程环境 `RSI_API_KEY` / `COSENS_API_KEY`,SDK 本身不自动加载 `.env`。CN grant 路径尚未部署,以上代码需待服务上线后联调;离线契约测试已通过。
@@ -0,0 +1,26 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.25"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "cosens-sdk"
7
+ version = "0.1.0"
8
+ description = "CoSens Python SDK for OpenAI and RSI workflows"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ dependencies = ["httpx>=0.27,<1", "openai>=2.54,<2.55"]
12
+
13
+ [project.optional-dependencies]
14
+ agents = ["openai-agents>=0.20,<0.21"]
15
+ examples = ["openai-agents>=0.20,<0.21", "python-dotenv>=1,<2"]
16
+ test = ["pytest>=8", "pytest-asyncio>=0.24", "build>=1"]
17
+
18
+ [tool.hatch.build.targets.wheel]
19
+ packages = ["src/cosens"]
20
+
21
+ [tool.hatch.build.targets.sdist]
22
+ only-include = ["src/cosens", "README.md", "pyproject.toml", "docs/api-reference.md"]
23
+
24
+ [tool.pytest.ini_options]
25
+ testpaths = ["tests"]
26
+ asyncio_mode = "auto"