tena 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.
- tena-0.1.0/.gitignore +18 -0
- tena-0.1.0/.python-version +1 -0
- tena-0.1.0/AGENTS.md +18 -0
- tena-0.1.0/PKG-INFO +227 -0
- tena-0.1.0/README.md +215 -0
- tena-0.1.0/pyproject.toml +24 -0
- tena-0.1.0/tena/__init__.py +3 -0
- tena-0.1.0/tena/image.py +990 -0
- tena-0.1.0/tena/main.py +168 -0
- tena-0.1.0/tests/integration/test_draw_live.py +81 -0
- tena-0.1.0/uv.lock +954 -0
tena-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
tena-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
始终使用英文来思考,使用中文来回复用户和完成计划
|
|
4
|
+
|
|
5
|
+
关于项目的详细描述 ./README.md
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- Python 3.10 or higher
|
|
10
|
+
- uv package manager
|
|
11
|
+
|
|
12
|
+
## Development Guidelines
|
|
13
|
+
|
|
14
|
+
- 不要 git 提交代码,除非用户明确要求
|
|
15
|
+
- 对于复杂的逻辑使用清晰的注释来描述
|
|
16
|
+
- 涉及到项目结构调整,要同步更新 README.md 中的相关内容
|
|
17
|
+
- 除非明确要求,你不用写测试代码。除了编译检查/lint,你不用运行代码进行测试,可以提醒我如何手动运行。
|
|
18
|
+
- 尽可能使用明确的类型标注
|
tena-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tena
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: My Text-to-Image kits
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Requires-Dist: google-genai>=2.10.0
|
|
7
|
+
Requires-Dist: httpx>=0.28.1
|
|
8
|
+
Requires-Dist: openai>=2.44.0
|
|
9
|
+
Requires-Dist: pytest>=9.0.2
|
|
10
|
+
Requires-Dist: python-dotenv>=1.2.1
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# tena
|
|
14
|
+
|
|
15
|
+
`tena` provides a small async wrapper for text-to-image model calls.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
Prerequisites:
|
|
20
|
+
|
|
21
|
+
- Python 3.10+
|
|
22
|
+
- uv
|
|
23
|
+
|
|
24
|
+
Dependencies are declared in `pyproject.toml`:
|
|
25
|
+
|
|
26
|
+
- `openai`
|
|
27
|
+
- `google-genai`
|
|
28
|
+
- `httpx`
|
|
29
|
+
- `pytest`
|
|
30
|
+
- `python-dotenv`
|
|
31
|
+
|
|
32
|
+
## Image generation
|
|
33
|
+
|
|
34
|
+
### Python API
|
|
35
|
+
|
|
36
|
+
Use `draw` with a registered `model_path`. The function returns a list of
|
|
37
|
+
`GeneratedImage` objects. Each object contains image bytes and a MIME type.
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
import asyncio
|
|
41
|
+
from pathlib import Path
|
|
42
|
+
|
|
43
|
+
from tena import draw, suffix_for_mime_type
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
async def main() -> None:
|
|
47
|
+
images = await draw(
|
|
48
|
+
model_path="openrouter/gpt-image-2",
|
|
49
|
+
prompt="A clean product photo of a ceramic cup",
|
|
50
|
+
size="1024x1024",
|
|
51
|
+
number=1,
|
|
52
|
+
input_images=[
|
|
53
|
+
"./reference-1.png",
|
|
54
|
+
"https://example.com/reference-2.png",
|
|
55
|
+
],
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
image = images[0]
|
|
59
|
+
suffix = suffix_for_mime_type(image.mime_type)
|
|
60
|
+
Path(f"result{suffix}").write_bytes(image.data)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
asyncio.run(main())
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The package exports the reusable API from `tena/__init__.py`. `tena/main.py` is
|
|
67
|
+
only the CLI entrypoint; core image generation logic lives in `tena/image.py`.
|
|
68
|
+
|
|
69
|
+
### CLI
|
|
70
|
+
|
|
71
|
+
The `tena` command is a thin wrapper around the Python API.
|
|
72
|
+
|
|
73
|
+
Generate one image and write it to a required output path:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
uv run tena --model-path openrouter/gpt-image-2 --prompt "A clean product photo of a ceramic cup" --output ./result.png --size 1024x1024
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The output path supports `~`, including `--output ~/Downloads/result.png` and
|
|
80
|
+
`--output=~/Downloads/result.png`.
|
|
81
|
+
|
|
82
|
+
Use `-` as the prompt to read from stdin:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
echo "A simple red cube on a clean white background" | uv run tena --model-path openrouter/gpt-image-2 --prompt - --output ./result.png --size 1024x1024
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Generate multiple images with `--number`. The first image uses the exact output
|
|
89
|
+
path, and later images are numbered:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
uv run tena --model-path zenmux/gpt-image-2 --prompt "A blue sphere" --output ./result.png --number 2 --size 1024x1024
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
This writes `result.png` and `result-2.png`.
|
|
96
|
+
|
|
97
|
+
Provide reference images with repeated `--input-image` arguments. Each value can
|
|
98
|
+
be a local file path or an `http`/`https` URL:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
uv run tena \
|
|
102
|
+
--model-path openrouter/gpt-image-2 \
|
|
103
|
+
--prompt "Create a studio product photo using the reference objects" \
|
|
104
|
+
--input-image ./reference-1.png \
|
|
105
|
+
--input-image https://example.com/reference-2.png \
|
|
106
|
+
--output ./result.png \
|
|
107
|
+
--size 1024x1024
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
URL images are downloaded to `/tmp/tena/input_images` and cached by URL, so the
|
|
111
|
+
same URL is reused on later runs instead of downloaded again.
|
|
112
|
+
|
|
113
|
+
CLI logs are written to stderr and default to `INFO`. The generated output paths
|
|
114
|
+
are still written to stdout. Use `--log-level WARNING` to hide normal progress
|
|
115
|
+
logs, or `--log-level DEBUG` for diagnostic details:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
uv run tena --model-path openrouter/gpt-image-2 --prompt "A blue sphere" --output ./result.png --log-level WARNING
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
INFO logs include concise request metadata, URL cache/download status, byte
|
|
122
|
+
counts, and elapsed times. DEBUG logs include more detailed SDK and input image
|
|
123
|
+
diagnostics. Logs do not include API keys, full prompts, full input URLs, or
|
|
124
|
+
image data.
|
|
125
|
+
|
|
126
|
+
### Return object
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
@dataclass(frozen=True)
|
|
130
|
+
class GeneratedImage:
|
|
131
|
+
data: bytes
|
|
132
|
+
mime_type: str
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Registered models
|
|
136
|
+
|
|
137
|
+
Models are currently registered in code. `model_path` is the lookup key, and
|
|
138
|
+
`model_realname` is the model id sent to the upstream API.
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
@dataclass(frozen=True)
|
|
142
|
+
class ImageModel:
|
|
143
|
+
model_displayname: str
|
|
144
|
+
model_realname: str
|
|
145
|
+
client: Literal[
|
|
146
|
+
"openai",
|
|
147
|
+
"openrouter",
|
|
148
|
+
"gemini-interactions",
|
|
149
|
+
"gemini-generate-content",
|
|
150
|
+
]
|
|
151
|
+
api_key_env: str
|
|
152
|
+
base_url: str | None = None
|
|
153
|
+
default_mime_type: str = "image/png"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Current model paths:
|
|
157
|
+
|
|
158
|
+
- `302ai/gpt-image-2`
|
|
159
|
+
- `302ai/gemini-3.1-flash-image-preview`
|
|
160
|
+
- `google/gemini-3.1-flash-image`
|
|
161
|
+
- `openrouter/gpt-image-2`
|
|
162
|
+
- `zenmux/gpt-image-2`
|
|
163
|
+
- `zenmux/gemini-3.1-flash-image`
|
|
164
|
+
|
|
165
|
+
`client` means which upstream API contract is used. OpenAI-compatible gateways
|
|
166
|
+
can use `client="openai"` with a custom `base_url`. OpenRouter uses
|
|
167
|
+
`client="openrouter"` and calls its `/images` unified image generation endpoint
|
|
168
|
+
directly.
|
|
169
|
+
|
|
170
|
+
Gemini image models use two different API contracts:
|
|
171
|
+
|
|
172
|
+
- `gemini-interactions` uses Google's Interactions API and is used for direct
|
|
173
|
+
Google Gemini access.
|
|
174
|
+
- `gemini-generate-content` uses the Generate Content API and is used for
|
|
175
|
+
Gemini-compatible gateways such as Zenmux and 302AI.
|
|
176
|
+
|
|
177
|
+
### Environment variables
|
|
178
|
+
|
|
179
|
+
Set the API key required by the selected model entry. Values can be provided by
|
|
180
|
+
the process environment or by a project-root `.env` file:
|
|
181
|
+
|
|
182
|
+
- `OPENROUTER_API_KEY`
|
|
183
|
+
- `ZENMUX_API_KEY`
|
|
184
|
+
- `AI302_API_KEY`
|
|
185
|
+
- `GEMINI_API_KEY`
|
|
186
|
+
|
|
187
|
+
### Gemini size format
|
|
188
|
+
|
|
189
|
+
Gemini image models use a single `size` string that is parsed into
|
|
190
|
+
the Gemini image response configuration. Interactions requests use
|
|
191
|
+
`response_format`; Generate Content requests use `image_config`.
|
|
192
|
+
|
|
193
|
+
- `16:9` -> `aspect_ratio`
|
|
194
|
+
- `2K` or `4K` -> `image_size`
|
|
195
|
+
- `16:9@2K` -> both `aspect_ratio` and `image_size`
|
|
196
|
+
- `auto` -> no explicit Gemini `response_format`
|
|
197
|
+
|
|
198
|
+
OpenAI-compatible and OpenRouter clients pass `size` through as the API `size`
|
|
199
|
+
parameter.
|
|
200
|
+
|
|
201
|
+
## Not implemented yet
|
|
202
|
+
|
|
203
|
+
The following parameters are part of the public function signature but are not
|
|
204
|
+
implemented yet:
|
|
205
|
+
|
|
206
|
+
- `web_search`
|
|
207
|
+
|
|
208
|
+
Passing `web_search` raises `NotImplementedError`.
|
|
209
|
+
|
|
210
|
+
## Integration tests
|
|
211
|
+
|
|
212
|
+
Live image generation tests are grouped under `tests/integration`. Set the API
|
|
213
|
+
key for the model you want to test in the environment or in the project `.env`
|
|
214
|
+
file:
|
|
215
|
+
|
|
216
|
+
- `OPENROUTER_API_KEY` for `openrouter/gpt-image-2`
|
|
217
|
+
- `ZENMUX_API_KEY` for `zenmux/gpt-image-2`
|
|
218
|
+
|
|
219
|
+
Then run:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
pytest tests/integration
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Tests with missing API keys are skipped. When a test succeeds, it writes the
|
|
226
|
+
generated image to `~/Downloads` with a `tena-<provider>-gpt-image-2` filename
|
|
227
|
+
prefix.
|
tena-0.1.0/README.md
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# tena
|
|
2
|
+
|
|
3
|
+
`tena` provides a small async wrapper for text-to-image model calls.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
Prerequisites:
|
|
8
|
+
|
|
9
|
+
- Python 3.10+
|
|
10
|
+
- uv
|
|
11
|
+
|
|
12
|
+
Dependencies are declared in `pyproject.toml`:
|
|
13
|
+
|
|
14
|
+
- `openai`
|
|
15
|
+
- `google-genai`
|
|
16
|
+
- `httpx`
|
|
17
|
+
- `pytest`
|
|
18
|
+
- `python-dotenv`
|
|
19
|
+
|
|
20
|
+
## Image generation
|
|
21
|
+
|
|
22
|
+
### Python API
|
|
23
|
+
|
|
24
|
+
Use `draw` with a registered `model_path`. The function returns a list of
|
|
25
|
+
`GeneratedImage` objects. Each object contains image bytes and a MIME type.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
import asyncio
|
|
29
|
+
from pathlib import Path
|
|
30
|
+
|
|
31
|
+
from tena import draw, suffix_for_mime_type
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
async def main() -> None:
|
|
35
|
+
images = await draw(
|
|
36
|
+
model_path="openrouter/gpt-image-2",
|
|
37
|
+
prompt="A clean product photo of a ceramic cup",
|
|
38
|
+
size="1024x1024",
|
|
39
|
+
number=1,
|
|
40
|
+
input_images=[
|
|
41
|
+
"./reference-1.png",
|
|
42
|
+
"https://example.com/reference-2.png",
|
|
43
|
+
],
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
image = images[0]
|
|
47
|
+
suffix = suffix_for_mime_type(image.mime_type)
|
|
48
|
+
Path(f"result{suffix}").write_bytes(image.data)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
asyncio.run(main())
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The package exports the reusable API from `tena/__init__.py`. `tena/main.py` is
|
|
55
|
+
only the CLI entrypoint; core image generation logic lives in `tena/image.py`.
|
|
56
|
+
|
|
57
|
+
### CLI
|
|
58
|
+
|
|
59
|
+
The `tena` command is a thin wrapper around the Python API.
|
|
60
|
+
|
|
61
|
+
Generate one image and write it to a required output path:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
uv run tena --model-path openrouter/gpt-image-2 --prompt "A clean product photo of a ceramic cup" --output ./result.png --size 1024x1024
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The output path supports `~`, including `--output ~/Downloads/result.png` and
|
|
68
|
+
`--output=~/Downloads/result.png`.
|
|
69
|
+
|
|
70
|
+
Use `-` as the prompt to read from stdin:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
echo "A simple red cube on a clean white background" | uv run tena --model-path openrouter/gpt-image-2 --prompt - --output ./result.png --size 1024x1024
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Generate multiple images with `--number`. The first image uses the exact output
|
|
77
|
+
path, and later images are numbered:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
uv run tena --model-path zenmux/gpt-image-2 --prompt "A blue sphere" --output ./result.png --number 2 --size 1024x1024
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
This writes `result.png` and `result-2.png`.
|
|
84
|
+
|
|
85
|
+
Provide reference images with repeated `--input-image` arguments. Each value can
|
|
86
|
+
be a local file path or an `http`/`https` URL:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
uv run tena \
|
|
90
|
+
--model-path openrouter/gpt-image-2 \
|
|
91
|
+
--prompt "Create a studio product photo using the reference objects" \
|
|
92
|
+
--input-image ./reference-1.png \
|
|
93
|
+
--input-image https://example.com/reference-2.png \
|
|
94
|
+
--output ./result.png \
|
|
95
|
+
--size 1024x1024
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
URL images are downloaded to `/tmp/tena/input_images` and cached by URL, so the
|
|
99
|
+
same URL is reused on later runs instead of downloaded again.
|
|
100
|
+
|
|
101
|
+
CLI logs are written to stderr and default to `INFO`. The generated output paths
|
|
102
|
+
are still written to stdout. Use `--log-level WARNING` to hide normal progress
|
|
103
|
+
logs, or `--log-level DEBUG` for diagnostic details:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
uv run tena --model-path openrouter/gpt-image-2 --prompt "A blue sphere" --output ./result.png --log-level WARNING
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
INFO logs include concise request metadata, URL cache/download status, byte
|
|
110
|
+
counts, and elapsed times. DEBUG logs include more detailed SDK and input image
|
|
111
|
+
diagnostics. Logs do not include API keys, full prompts, full input URLs, or
|
|
112
|
+
image data.
|
|
113
|
+
|
|
114
|
+
### Return object
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
@dataclass(frozen=True)
|
|
118
|
+
class GeneratedImage:
|
|
119
|
+
data: bytes
|
|
120
|
+
mime_type: str
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Registered models
|
|
124
|
+
|
|
125
|
+
Models are currently registered in code. `model_path` is the lookup key, and
|
|
126
|
+
`model_realname` is the model id sent to the upstream API.
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
@dataclass(frozen=True)
|
|
130
|
+
class ImageModel:
|
|
131
|
+
model_displayname: str
|
|
132
|
+
model_realname: str
|
|
133
|
+
client: Literal[
|
|
134
|
+
"openai",
|
|
135
|
+
"openrouter",
|
|
136
|
+
"gemini-interactions",
|
|
137
|
+
"gemini-generate-content",
|
|
138
|
+
]
|
|
139
|
+
api_key_env: str
|
|
140
|
+
base_url: str | None = None
|
|
141
|
+
default_mime_type: str = "image/png"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Current model paths:
|
|
145
|
+
|
|
146
|
+
- `302ai/gpt-image-2`
|
|
147
|
+
- `302ai/gemini-3.1-flash-image-preview`
|
|
148
|
+
- `google/gemini-3.1-flash-image`
|
|
149
|
+
- `openrouter/gpt-image-2`
|
|
150
|
+
- `zenmux/gpt-image-2`
|
|
151
|
+
- `zenmux/gemini-3.1-flash-image`
|
|
152
|
+
|
|
153
|
+
`client` means which upstream API contract is used. OpenAI-compatible gateways
|
|
154
|
+
can use `client="openai"` with a custom `base_url`. OpenRouter uses
|
|
155
|
+
`client="openrouter"` and calls its `/images` unified image generation endpoint
|
|
156
|
+
directly.
|
|
157
|
+
|
|
158
|
+
Gemini image models use two different API contracts:
|
|
159
|
+
|
|
160
|
+
- `gemini-interactions` uses Google's Interactions API and is used for direct
|
|
161
|
+
Google Gemini access.
|
|
162
|
+
- `gemini-generate-content` uses the Generate Content API and is used for
|
|
163
|
+
Gemini-compatible gateways such as Zenmux and 302AI.
|
|
164
|
+
|
|
165
|
+
### Environment variables
|
|
166
|
+
|
|
167
|
+
Set the API key required by the selected model entry. Values can be provided by
|
|
168
|
+
the process environment or by a project-root `.env` file:
|
|
169
|
+
|
|
170
|
+
- `OPENROUTER_API_KEY`
|
|
171
|
+
- `ZENMUX_API_KEY`
|
|
172
|
+
- `AI302_API_KEY`
|
|
173
|
+
- `GEMINI_API_KEY`
|
|
174
|
+
|
|
175
|
+
### Gemini size format
|
|
176
|
+
|
|
177
|
+
Gemini image models use a single `size` string that is parsed into
|
|
178
|
+
the Gemini image response configuration. Interactions requests use
|
|
179
|
+
`response_format`; Generate Content requests use `image_config`.
|
|
180
|
+
|
|
181
|
+
- `16:9` -> `aspect_ratio`
|
|
182
|
+
- `2K` or `4K` -> `image_size`
|
|
183
|
+
- `16:9@2K` -> both `aspect_ratio` and `image_size`
|
|
184
|
+
- `auto` -> no explicit Gemini `response_format`
|
|
185
|
+
|
|
186
|
+
OpenAI-compatible and OpenRouter clients pass `size` through as the API `size`
|
|
187
|
+
parameter.
|
|
188
|
+
|
|
189
|
+
## Not implemented yet
|
|
190
|
+
|
|
191
|
+
The following parameters are part of the public function signature but are not
|
|
192
|
+
implemented yet:
|
|
193
|
+
|
|
194
|
+
- `web_search`
|
|
195
|
+
|
|
196
|
+
Passing `web_search` raises `NotImplementedError`.
|
|
197
|
+
|
|
198
|
+
## Integration tests
|
|
199
|
+
|
|
200
|
+
Live image generation tests are grouped under `tests/integration`. Set the API
|
|
201
|
+
key for the model you want to test in the environment or in the project `.env`
|
|
202
|
+
file:
|
|
203
|
+
|
|
204
|
+
- `OPENROUTER_API_KEY` for `openrouter/gpt-image-2`
|
|
205
|
+
- `ZENMUX_API_KEY` for `zenmux/gpt-image-2`
|
|
206
|
+
|
|
207
|
+
Then run:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
pytest tests/integration
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Tests with missing API keys are skipped. When a test succeeds, it writes the
|
|
214
|
+
generated image to `~/Downloads` with a `tena-<provider>-gpt-image-2` filename
|
|
215
|
+
prefix.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "tena"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "My Text-to-Image kits"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"google-genai>=2.10.0",
|
|
9
|
+
"httpx>=0.28.1",
|
|
10
|
+
"openai>=2.44.0",
|
|
11
|
+
"pytest>=9.0.2",
|
|
12
|
+
"python-dotenv>=1.2.1",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[project.scripts]
|
|
16
|
+
tena = "tena.main:main"
|
|
17
|
+
|
|
18
|
+
[build-system]
|
|
19
|
+
requires = ["hatchling"]
|
|
20
|
+
build-backend = "hatchling.build"
|
|
21
|
+
|
|
22
|
+
[tool.pytest.ini_options]
|
|
23
|
+
pythonpath = ["."]
|
|
24
|
+
testpaths = ["tests"]
|