vokit 0.1.4__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.
- vokit-0.1.4/PKG-INFO +109 -0
- vokit-0.1.4/README.md +88 -0
- vokit-0.1.4/pyproject.toml +51 -0
- vokit-0.1.4/setup.cfg +4 -0
- vokit-0.1.4/tests/test_aiohttp_handler.py +50 -0
- vokit-0.1.4/tests/test_api.py +713 -0
- vokit-0.1.4/tests/test_client.py +84 -0
- vokit-0.1.4/tests/test_client_errors.py +123 -0
- vokit-0.1.4/tests/test_config.py +57 -0
- vokit-0.1.4/tests/test_config_threadsafe.py +39 -0
- vokit-0.1.4/tests/test_dev_mode.py +41 -0
- vokit-0.1.4/tests/test_errors.py +51 -0
- vokit-0.1.4/tests/test_init.py +48 -0
- vokit-0.1.4/tests/test_intercept_fail_fast.py +192 -0
- vokit-0.1.4/tests/test_interceptor.py +106 -0
- vokit-0.1.4/tests/test_interceptor_querystring.py +51 -0
- vokit-0.1.4/tests/test_models.py +39 -0
- vokit-0.1.4/tests/test_patcher.py +54 -0
- vokit-0.1.4/tests/test_providers.py +231 -0
- vokit-0.1.4/tests/test_urllib3_intercept.py +162 -0
- vokit-0.1.4/vokit/__init__.py +51 -0
- vokit-0.1.4/vokit/_api.py +222 -0
- vokit-0.1.4/vokit/_client.py +81 -0
- vokit-0.1.4/vokit/_config.py +74 -0
- vokit-0.1.4/vokit/_errors.py +45 -0
- vokit-0.1.4/vokit/_interceptor.py +137 -0
- vokit-0.1.4/vokit/_models.py +79 -0
- vokit-0.1.4/vokit/_patcher.py +270 -0
- vokit-0.1.4/vokit/_providers.py +139 -0
- vokit-0.1.4/vokit.egg-info/PKG-INFO +109 -0
- vokit-0.1.4/vokit.egg-info/SOURCES.txt +32 -0
- vokit-0.1.4/vokit.egg-info/dependency_links.txt +1 -0
- vokit-0.1.4/vokit.egg-info/requires.txt +13 -0
- vokit-0.1.4/vokit.egg-info/top_level.txt +1 -0
vokit-0.1.4/PKG-INFO
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vokit
|
|
3
|
+
Version: 0.1.4
|
|
4
|
+
Summary: VirtualOffice Agent SDK — 透明拦截转发 + 平台 API 封装
|
|
5
|
+
Author: VirtualOffice Team
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: wrapt>=1.15
|
|
10
|
+
Requires-Dist: httpx>=0.24
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
13
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
14
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
15
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
16
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
17
|
+
Requires-Dist: aiohttp>=3.8; extra == "dev"
|
|
18
|
+
Requires-Dist: requests>=2.28; extra == "dev"
|
|
19
|
+
Requires-Dist: urllib3>=1.26; extra == "dev"
|
|
20
|
+
Requires-Dist: respx>=0.21; extra == "dev"
|
|
21
|
+
|
|
22
|
+
# vokit — VirtualOffice Agent SDK
|
|
23
|
+
|
|
24
|
+
一行 `import vokit` 完成拦截激活 + API 就绪。
|
|
25
|
+
|
|
26
|
+
## 安装
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# 预发布版本
|
|
30
|
+
pip install git+http://oauth2:YOUR_TOKEN@gitlab.deepleaper.com/deepbrain/vokit-sdk.git@prerelease
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 快速开始
|
|
34
|
+
|
|
35
|
+
### 1. 拦截 LLM 请求
|
|
36
|
+
|
|
37
|
+
在 Agent 的**入口文件最顶部** import 一次即可:
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
import vokit
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- **只需 import 一次**:patch 注册在进程级别的 HTTP 库入口,全局生效。
|
|
44
|
+
- **放在最顶部**:确保在所有 LLM SDK 被 import 之前 patch 已注册好。
|
|
45
|
+
- **幂等安全**:多次 import 不会重复注册。
|
|
46
|
+
|
|
47
|
+
### 2. 使用平台 API
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
import vokit
|
|
51
|
+
|
|
52
|
+
# 提交产出物
|
|
53
|
+
vokit.submit_output(
|
|
54
|
+
output_type="text",
|
|
55
|
+
content="分析报告内容..."
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# 查询工位资源
|
|
59
|
+
resources = vokit.get_resources()
|
|
60
|
+
|
|
61
|
+
# 上报任务状态
|
|
62
|
+
vokit.report_status(tasks=[
|
|
63
|
+
{"name": "task-1", "status": "running", "progress": 0.75},
|
|
64
|
+
])
|
|
65
|
+
|
|
66
|
+
# 上报指标数据
|
|
67
|
+
vokit.report_metrics(metrics=[
|
|
68
|
+
{"metricType": "tokens_used", "metricValue": 1500, "snapshotDate": "2026-04-14"},
|
|
69
|
+
])
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## 运行模式
|
|
73
|
+
|
|
74
|
+
### 开发模式
|
|
75
|
+
|
|
76
|
+
不设置 `VO_GATEWAY_URL` 和 `VO_ACCESS_TOKEN` 时自动进入:
|
|
77
|
+
- LLM 请求**直连** Provider,不被拦截
|
|
78
|
+
- 平台 API 返回 Mock 数据
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
export OPENAI_API_KEY="your-key"
|
|
82
|
+
python your_agent.py
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 生产模式
|
|
86
|
+
|
|
87
|
+
设置环境变量后自动进入:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
export VO_GATEWAY_URL=http://localhost:8888
|
|
91
|
+
export VO_ACCESS_TOKEN=<your-jwt-token>
|
|
92
|
+
export OPENAI_API_KEY="your-key"
|
|
93
|
+
python your_agent.py
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 环境变量
|
|
97
|
+
|
|
98
|
+
| 变量 | 说明 |
|
|
99
|
+
|------|------|
|
|
100
|
+
| `VO_GATEWAY_URL` | 内网网关地址,缺失则进入开发模式 |
|
|
101
|
+
| `VO_ACCESS_TOKEN` | 网关 Bearer Token,缺失则进入开发模式 |
|
|
102
|
+
|
|
103
|
+
## Python 版本
|
|
104
|
+
|
|
105
|
+
要求 Python 3.10+
|
|
106
|
+
|
|
107
|
+
## License
|
|
108
|
+
|
|
109
|
+
MIT
|
vokit-0.1.4/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# vokit — VirtualOffice Agent SDK
|
|
2
|
+
|
|
3
|
+
一行 `import vokit` 完成拦截激活 + API 就绪。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# 预发布版本
|
|
9
|
+
pip install git+http://oauth2:YOUR_TOKEN@gitlab.deepleaper.com/deepbrain/vokit-sdk.git@prerelease
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## 快速开始
|
|
13
|
+
|
|
14
|
+
### 1. 拦截 LLM 请求
|
|
15
|
+
|
|
16
|
+
在 Agent 的**入口文件最顶部** import 一次即可:
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
import vokit
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
- **只需 import 一次**:patch 注册在进程级别的 HTTP 库入口,全局生效。
|
|
23
|
+
- **放在最顶部**:确保在所有 LLM SDK 被 import 之前 patch 已注册好。
|
|
24
|
+
- **幂等安全**:多次 import 不会重复注册。
|
|
25
|
+
|
|
26
|
+
### 2. 使用平台 API
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
import vokit
|
|
30
|
+
|
|
31
|
+
# 提交产出物
|
|
32
|
+
vokit.submit_output(
|
|
33
|
+
output_type="text",
|
|
34
|
+
content="分析报告内容..."
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# 查询工位资源
|
|
38
|
+
resources = vokit.get_resources()
|
|
39
|
+
|
|
40
|
+
# 上报任务状态
|
|
41
|
+
vokit.report_status(tasks=[
|
|
42
|
+
{"name": "task-1", "status": "running", "progress": 0.75},
|
|
43
|
+
])
|
|
44
|
+
|
|
45
|
+
# 上报指标数据
|
|
46
|
+
vokit.report_metrics(metrics=[
|
|
47
|
+
{"metricType": "tokens_used", "metricValue": 1500, "snapshotDate": "2026-04-14"},
|
|
48
|
+
])
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 运行模式
|
|
52
|
+
|
|
53
|
+
### 开发模式
|
|
54
|
+
|
|
55
|
+
不设置 `VO_GATEWAY_URL` 和 `VO_ACCESS_TOKEN` 时自动进入:
|
|
56
|
+
- LLM 请求**直连** Provider,不被拦截
|
|
57
|
+
- 平台 API 返回 Mock 数据
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
export OPENAI_API_KEY="your-key"
|
|
61
|
+
python your_agent.py
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 生产模式
|
|
65
|
+
|
|
66
|
+
设置环境变量后自动进入:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
export VO_GATEWAY_URL=http://localhost:8888
|
|
70
|
+
export VO_ACCESS_TOKEN=<your-jwt-token>
|
|
71
|
+
export OPENAI_API_KEY="your-key"
|
|
72
|
+
python your_agent.py
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## 环境变量
|
|
76
|
+
|
|
77
|
+
| 变量 | 说明 |
|
|
78
|
+
|------|------|
|
|
79
|
+
| `VO_GATEWAY_URL` | 内网网关地址,缺失则进入开发模式 |
|
|
80
|
+
| `VO_ACCESS_TOKEN` | 网关 Bearer Token,缺失则进入开发模式 |
|
|
81
|
+
|
|
82
|
+
## Python 版本
|
|
83
|
+
|
|
84
|
+
要求 Python 3.10+
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MIT
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "vokit"
|
|
7
|
+
version = "0.1.4"
|
|
8
|
+
description = "VirtualOffice Agent SDK — 透明拦截转发 + 平台 API 封装"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "VirtualOffice Team" },
|
|
14
|
+
]
|
|
15
|
+
dependencies = [
|
|
16
|
+
"wrapt>=1.15",
|
|
17
|
+
"httpx>=0.24",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.optional-dependencies]
|
|
21
|
+
dev = [
|
|
22
|
+
"pytest>=7.0",
|
|
23
|
+
"pytest-cov>=4.0",
|
|
24
|
+
"pytest-asyncio>=0.21",
|
|
25
|
+
"ruff>=0.1.0",
|
|
26
|
+
"mypy>=1.0",
|
|
27
|
+
"aiohttp>=3.8",
|
|
28
|
+
"requests>=2.28",
|
|
29
|
+
"urllib3>=1.26",
|
|
30
|
+
"respx>=0.21",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[tool.setuptools.packages.find]
|
|
34
|
+
include = ["vokit*"]
|
|
35
|
+
|
|
36
|
+
[tool.ruff]
|
|
37
|
+
target-version = "py310"
|
|
38
|
+
line-length = 120
|
|
39
|
+
|
|
40
|
+
[tool.ruff.lint]
|
|
41
|
+
select = ["E", "F", "W", "I"]
|
|
42
|
+
|
|
43
|
+
[tool.pytest.ini_options]
|
|
44
|
+
testpaths = ["tests"]
|
|
45
|
+
asyncio_mode = "auto"
|
|
46
|
+
|
|
47
|
+
[tool.mypy]
|
|
48
|
+
python_version = "3.10"
|
|
49
|
+
strict = true
|
|
50
|
+
warn_return_any = true
|
|
51
|
+
warn_unused_configs = true
|
vokit-0.1.4/setup.cfg
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""aiohttp handler 专项测试。"""
|
|
2
|
+
from unittest.mock import AsyncMock, MagicMock, patch
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from vokit._patcher import _handle_aiohttp_async
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.mark.asyncio
|
|
10
|
+
async def test_handler_reads_headers_from_positional():
|
|
11
|
+
"""headers 通过位置参数 args[2] 传入时,handler 应正确读取并传递给 intercept_request。"""
|
|
12
|
+
original_headers = {"Authorization": "Bearer sk-xxx", "Content-Type": "application/json"}
|
|
13
|
+
new_headers = {"X-Vokit-Intercepted": "1", "Authorization": "Bearer gateway-token"}
|
|
14
|
+
|
|
15
|
+
with patch("vokit._patcher.intercept_request") as mock_intercept:
|
|
16
|
+
mock_intercept.return_value = ("http://gateway:8080/v1/chat", new_headers)
|
|
17
|
+
wrapped = AsyncMock(return_value=MagicMock(status=200))
|
|
18
|
+
|
|
19
|
+
# headers 作为第 3 个位置参数传入(method, url, headers)
|
|
20
|
+
await _handle_aiohttp_async(
|
|
21
|
+
wrapped, MagicMock(),
|
|
22
|
+
("POST", "https://api.openai.com/v1/chat/completions", original_headers),
|
|
23
|
+
{},
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# 验证 intercept_request 被调用且收到了原始 headers
|
|
27
|
+
call_args = mock_intercept.call_args
|
|
28
|
+
# call_args[0] = (url, body, headers)
|
|
29
|
+
assert call_args[0][0] == "https://api.openai.com/v1/chat/completions"
|
|
30
|
+
assert call_args[0][2] == original_headers
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@pytest.mark.asyncio
|
|
34
|
+
async def test_handler_headers_from_kwargs():
|
|
35
|
+
"""headers 通过 kwargs 传入时,handler 应正常工作。"""
|
|
36
|
+
original_headers = {"Authorization": "Bearer sk-xxx"}
|
|
37
|
+
new_headers = {"X-Vokit-Intercepted": "1"}
|
|
38
|
+
|
|
39
|
+
with patch("vokit._patcher.intercept_request") as mock_intercept:
|
|
40
|
+
mock_intercept.return_value = ("http://gateway:8080/v1/chat", new_headers)
|
|
41
|
+
wrapped = AsyncMock(return_value=MagicMock(status=200))
|
|
42
|
+
|
|
43
|
+
await _handle_aiohttp_async(
|
|
44
|
+
wrapped, MagicMock(),
|
|
45
|
+
("POST", "https://api.openai.com/v1/chat/completions"),
|
|
46
|
+
{"headers": original_headers},
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
call_args = mock_intercept.call_args
|
|
50
|
+
assert call_args[0][2] == original_headers
|