openai-pro-cli 2026.8.11.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.
Files changed (31) hide show
  1. openai_pro_cli-2026.8.11.0/.env.example +9 -0
  2. openai_pro_cli-2026.8.11.0/CHANGELOG.md +22 -0
  3. openai_pro_cli-2026.8.11.0/LICENSE +21 -0
  4. openai_pro_cli-2026.8.11.0/PKG-INFO +144 -0
  5. openai_pro_cli-2026.8.11.0/README.md +99 -0
  6. openai_pro_cli-2026.8.11.0/openai_cli/__init__.py +3 -0
  7. openai_pro_cli-2026.8.11.0/openai_cli/__main__.py +6 -0
  8. openai_pro_cli-2026.8.11.0/openai_cli/commands/__init__.py +1 -0
  9. openai_pro_cli-2026.8.11.0/openai_cli/commands/_json.py +46 -0
  10. openai_pro_cli-2026.8.11.0/openai_cli/commands/chat.py +301 -0
  11. openai_pro_cli-2026.8.11.0/openai_cli/commands/embed.py +78 -0
  12. openai_pro_cli-2026.8.11.0/openai_cli/commands/image.py +323 -0
  13. openai_pro_cli-2026.8.11.0/openai_cli/commands/info.py +45 -0
  14. openai_pro_cli-2026.8.11.0/openai_cli/commands/realtime.py +64 -0
  15. openai_pro_cli-2026.8.11.0/openai_cli/commands/response.py +115 -0
  16. openai_pro_cli-2026.8.11.0/openai_cli/commands/speech.py +100 -0
  17. openai_pro_cli-2026.8.11.0/openai_cli/commands/tasks.py +136 -0
  18. openai_pro_cli-2026.8.11.0/openai_cli/commands/transcribe.py +124 -0
  19. openai_pro_cli-2026.8.11.0/openai_cli/core/__init__.py +1 -0
  20. openai_pro_cli-2026.8.11.0/openai_cli/core/client.py +281 -0
  21. openai_pro_cli-2026.8.11.0/openai_cli/core/config.py +39 -0
  22. openai_pro_cli-2026.8.11.0/openai_cli/core/exceptions.py +37 -0
  23. openai_pro_cli-2026.8.11.0/openai_cli/core/output.py +466 -0
  24. openai_pro_cli-2026.8.11.0/openai_cli/main.py +86 -0
  25. openai_pro_cli-2026.8.11.0/pyproject.toml +117 -0
  26. openai_pro_cli-2026.8.11.0/tests/__init__.py +1 -0
  27. openai_pro_cli-2026.8.11.0/tests/conftest.py +166 -0
  28. openai_pro_cli-2026.8.11.0/tests/test_client.py +152 -0
  29. openai_pro_cli-2026.8.11.0/tests/test_commands.py +1157 -0
  30. openai_pro_cli-2026.8.11.0/tests/test_config.py +44 -0
  31. openai_pro_cli-2026.8.11.0/tests/test_integration.py +19 -0
@@ -0,0 +1,9 @@
1
+ # AceDataCloud API Token
2
+ # Get yours at https://platform.acedata.cloud
3
+ ACEDATACLOUD_API_TOKEN=
4
+
5
+ # Optional: Custom API base URL (default: https://api.acedata.cloud)
6
+ # ACEDATACLOUD_API_BASE_URL=https://api.acedata.cloud
7
+
8
+ # Optional: Request timeout in seconds (default: 30)
9
+ # OPENAI_REQUEST_TIMEOUT=30
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [0.2.0] - 2026-04-30
6
+
7
+ ### Added
8
+ - `chat` command: new options `--max-completion-tokens`, `--top-p`, `--frequency-penalty`, `--presence-penalty`, `--seed`, `--stop`, `--reasoning-effort`, `--user`, `--service-tier`
9
+ - `edit` command: new options `--mask-url`, `--partial-images`
10
+ - `response` command: new options `--count` (`-n`), `--response-format`
11
+
12
+ ## [0.1.0] - 2025-04-25
13
+
14
+ ### Added
15
+ - Initial release
16
+ - `chat` command for OpenAI-compatible chat completions
17
+ - `embed` command for text embeddings
18
+ - `image` command for image generation
19
+ - `edit` command for image editing
20
+ - `response` command for Responses API
21
+ - `models` info command listing available models
22
+ - `config` command to inspect current settings
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 AceDataCloud
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,144 @@
1
+ Metadata-Version: 2.1
2
+ Name: openai-pro-cli
3
+ Version: 2026.8.11.0
4
+ Summary: CLI tool for OpenAI-compatible APIs via AceDataCloud
5
+ Project-URL: Homepage, https://github.com/AceDataCloud/OpenAICli
6
+ Project-URL: Repository, https://github.com/AceDataCloud/OpenAICli
7
+ Project-URL: Issues, https://github.com/AceDataCloud/OpenAICli/issues
8
+ Project-URL: Changelog, https://github.com/AceDataCloud/OpenAICli/blob/main/CHANGELOG.md
9
+ Author-email: AceDataCloud <support@acedata.cloud>
10
+ Maintainer-email: AceDataCloud <support@acedata.cloud>
11
+ License: MIT
12
+ License-File: LICENSE
13
+ Keywords: acedata,chat,cli,command-line,embeddings,gpt,image-generation,openai
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Environment :: Console
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
24
+ Requires-Python: >=3.10
25
+ Requires-Dist: click>=8.1.0
26
+ Requires-Dist: httpx>=0.27.0
27
+ Requires-Dist: pydantic>=2.0.0
28
+ Requires-Dist: python-dotenv>=1.0.0
29
+ Requires-Dist: rich>=13.0.0
30
+ Provides-Extra: all
31
+ Requires-Dist: openai-pro-cli[dev,release,test]; extra == 'all'
32
+ Provides-Extra: dev
33
+ Requires-Dist: mypy>=1.10.0; extra == 'dev'
34
+ Requires-Dist: pre-commit>=3.7.0; extra == 'dev'
35
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
36
+ Provides-Extra: release
37
+ Requires-Dist: build>=1.2.0; extra == 'release'
38
+ Requires-Dist: twine>=6.1.0; extra == 'release'
39
+ Provides-Extra: test
40
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'test'
41
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'test'
42
+ Requires-Dist: pytest>=8.0.0; extra == 'test'
43
+ Requires-Dist: respx>=0.21.0; extra == 'test'
44
+ Description-Content-Type: text/markdown
45
+
46
+ # OpenAI CLI
47
+
48
+ A command-line tool for OpenAI-compatible APIs via [AceDataCloud](https://platform.acedata.cloud).
49
+
50
+ ## Installation
51
+
52
+ ```bash
53
+ pip install openai-pro-cli
54
+ ```
55
+
56
+ ## Quick Start
57
+
58
+ ### 1. Get an API Token
59
+
60
+ Sign up at [https://platform.acedata.cloud](https://platform.acedata.cloud) and get your API token.
61
+
62
+ ### 2. Configure
63
+
64
+ ```bash
65
+ export ACEDATACLOUD_API_TOKEN=your_token_here
66
+ ```
67
+
68
+ Or save it to a `.env` file:
69
+
70
+ ```bash
71
+ cp .env.example .env
72
+ # Edit .env and set ACEDATACLOUD_API_TOKEN
73
+ ```
74
+
75
+ ### 3. Use
76
+
77
+ ```bash
78
+ # Chat with a model
79
+ openai-cli chat "What is the capital of France?"
80
+
81
+ # Chat with a specific model
82
+ openai-cli chat "Explain quantum computing" -m gpt-5.4
83
+
84
+ # Generate embeddings
85
+ openai-cli embed "Hello, world!" -m text-embedding-3-small
86
+
87
+ # Generate an image
88
+ openai-cli image "A futuristic city skyline at night"
89
+
90
+ # Edit an image
91
+ openai-cli edit "Add a rainbow" --image-url https://example.com/photo.jpg
92
+
93
+ # Use the Responses API
94
+ openai-cli response "Summarize this article" -m gpt-4o
95
+
96
+ # Synthesize speech audio
97
+ openai-cli speech "Hello from AceDataCloud" --voice nova --output hello.mp3
98
+
99
+ # Show realtime WebSocket connection details
100
+ openai-cli realtime --model gpt-realtime
101
+
102
+ # Retrieve an async task result
103
+ openai-cli tasks retrieve --id 7489df4c-ef03-4de0-b598-e9a590793434
104
+ openai-cli tasks retrieve --trace-id my-custom-trace-001
105
+
106
+ # Retrieve a batch of task results
107
+ openai-cli tasks batch --trace-ids trace-001 trace-002
108
+
109
+ # List available models
110
+ openai-cli models
111
+
112
+ # Show configuration
113
+ openai-cli config
114
+ ```
115
+
116
+ ## Commands
117
+
118
+ | Command | Description |
119
+ |---------|-------------|
120
+ | `chat` | Chat completions (`/openai/chat/completions`) |
121
+ | `embed` | Text embeddings (`/openai/embeddings`) |
122
+ | `image` | Image generation (`/openai/images/generations`) |
123
+ | `edit` | Image editing (`/openai/images/edits`) |
124
+ | `response` | Responses API (`/openai/responses`) |
125
+ | `speech` | Speech synthesis (`/v1/audio/speech`) |
126
+ | `realtime` | Realtime WebSocket connection info (`/v1/realtime`) |
127
+ | `tasks retrieve` | Retrieve a single async task result (`/openai/tasks`) |
128
+ | `tasks batch` | Retrieve multiple async task results (`/openai/tasks`) |
129
+ | `models` | List available models (`/openai/models`) |
130
+ | `config` | Show current configuration |
131
+
132
+ ## Environment Variables
133
+
134
+ | Variable | Description | Default |
135
+ |----------|-------------|---------|
136
+ | `ACEDATACLOUD_API_TOKEN` | Your API token (required) | — |
137
+ | `ACEDATACLOUD_API_BASE_URL` | API base URL | `https://api.acedata.cloud` |
138
+ | `OPENAI_REQUEST_TIMEOUT` | Request timeout in seconds | `30` |
139
+
140
+ ## Docker
141
+
142
+ ```bash
143
+ docker compose run --rm openai-cli chat "Hello!" -m gpt-4o
144
+ ```
@@ -0,0 +1,99 @@
1
+ # OpenAI CLI
2
+
3
+ A command-line tool for OpenAI-compatible APIs via [AceDataCloud](https://platform.acedata.cloud).
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install openai-pro-cli
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ### 1. Get an API Token
14
+
15
+ Sign up at [https://platform.acedata.cloud](https://platform.acedata.cloud) and get your API token.
16
+
17
+ ### 2. Configure
18
+
19
+ ```bash
20
+ export ACEDATACLOUD_API_TOKEN=your_token_here
21
+ ```
22
+
23
+ Or save it to a `.env` file:
24
+
25
+ ```bash
26
+ cp .env.example .env
27
+ # Edit .env and set ACEDATACLOUD_API_TOKEN
28
+ ```
29
+
30
+ ### 3. Use
31
+
32
+ ```bash
33
+ # Chat with a model
34
+ openai-cli chat "What is the capital of France?"
35
+
36
+ # Chat with a specific model
37
+ openai-cli chat "Explain quantum computing" -m gpt-5.4
38
+
39
+ # Generate embeddings
40
+ openai-cli embed "Hello, world!" -m text-embedding-3-small
41
+
42
+ # Generate an image
43
+ openai-cli image "A futuristic city skyline at night"
44
+
45
+ # Edit an image
46
+ openai-cli edit "Add a rainbow" --image-url https://example.com/photo.jpg
47
+
48
+ # Use the Responses API
49
+ openai-cli response "Summarize this article" -m gpt-4o
50
+
51
+ # Synthesize speech audio
52
+ openai-cli speech "Hello from AceDataCloud" --voice nova --output hello.mp3
53
+
54
+ # Show realtime WebSocket connection details
55
+ openai-cli realtime --model gpt-realtime
56
+
57
+ # Retrieve an async task result
58
+ openai-cli tasks retrieve --id 7489df4c-ef03-4de0-b598-e9a590793434
59
+ openai-cli tasks retrieve --trace-id my-custom-trace-001
60
+
61
+ # Retrieve a batch of task results
62
+ openai-cli tasks batch --trace-ids trace-001 trace-002
63
+
64
+ # List available models
65
+ openai-cli models
66
+
67
+ # Show configuration
68
+ openai-cli config
69
+ ```
70
+
71
+ ## Commands
72
+
73
+ | Command | Description |
74
+ |---------|-------------|
75
+ | `chat` | Chat completions (`/openai/chat/completions`) |
76
+ | `embed` | Text embeddings (`/openai/embeddings`) |
77
+ | `image` | Image generation (`/openai/images/generations`) |
78
+ | `edit` | Image editing (`/openai/images/edits`) |
79
+ | `response` | Responses API (`/openai/responses`) |
80
+ | `speech` | Speech synthesis (`/v1/audio/speech`) |
81
+ | `realtime` | Realtime WebSocket connection info (`/v1/realtime`) |
82
+ | `tasks retrieve` | Retrieve a single async task result (`/openai/tasks`) |
83
+ | `tasks batch` | Retrieve multiple async task results (`/openai/tasks`) |
84
+ | `models` | List available models (`/openai/models`) |
85
+ | `config` | Show current configuration |
86
+
87
+ ## Environment Variables
88
+
89
+ | Variable | Description | Default |
90
+ |----------|-------------|---------|
91
+ | `ACEDATACLOUD_API_TOKEN` | Your API token (required) | — |
92
+ | `ACEDATACLOUD_API_BASE_URL` | API base URL | `https://api.acedata.cloud` |
93
+ | `OPENAI_REQUEST_TIMEOUT` | Request timeout in seconds | `30` |
94
+
95
+ ## Docker
96
+
97
+ ```bash
98
+ docker compose run --rm openai-cli chat "Hello!" -m gpt-4o
99
+ ```
@@ -0,0 +1,3 @@
1
+ """OpenAI CLI - Command-line tool for OpenAI-compatible APIs via AceDataCloud."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,6 @@
1
+ """Entry point for running as a module: python -m openai_cli."""
2
+
3
+ from openai_cli.main import cli
4
+
5
+ if __name__ == "__main__":
6
+ cli()
@@ -0,0 +1 @@
1
+ """OpenAI CLI commands package."""
@@ -0,0 +1,46 @@
1
+ """Helpers for parsing JSON-valued CLI options."""
2
+
3
+ import json
4
+ from typing import Any
5
+
6
+ import click
7
+
8
+
9
+ def parse_json_value(value: str | None, option_name: str) -> Any:
10
+ """Parse a CLI option as JSON."""
11
+ if value is None:
12
+ return None
13
+ try:
14
+ return json.loads(value)
15
+ except json.JSONDecodeError as exc:
16
+ raise click.BadParameter(f"{option_name} must be valid JSON.") from exc
17
+
18
+
19
+ def parse_json_object(value: str | None, option_name: str) -> dict[str, Any] | None:
20
+ """Parse a CLI option as a JSON object."""
21
+ parsed = parse_json_value(value, option_name)
22
+ if parsed is None:
23
+ return None
24
+ if not isinstance(parsed, dict):
25
+ raise click.BadParameter(f"{option_name} must be a JSON object.")
26
+ return parsed
27
+
28
+
29
+ def parse_json_array(value: str | None, option_name: str) -> list[Any] | None:
30
+ """Parse a CLI option as a JSON array."""
31
+ parsed = parse_json_value(value, option_name)
32
+ if parsed is None:
33
+ return None
34
+ if not isinstance(parsed, list):
35
+ raise click.BadParameter(f"{option_name} must be a JSON array.")
36
+ return parsed
37
+
38
+
39
+ def parse_json_or_string(value: str | None, option_name: str) -> Any:
40
+ """Parse JSON when possible, otherwise keep plain strings."""
41
+ if value is None:
42
+ return None
43
+ stripped = value.strip()
44
+ if stripped.startswith("{") or stripped.startswith("["):
45
+ return parse_json_value(value, option_name)
46
+ return value
@@ -0,0 +1,301 @@
1
+ """Chat completion command."""
2
+
3
+ import click
4
+
5
+ from openai_cli.commands._json import (
6
+ parse_json_array,
7
+ parse_json_object,
8
+ parse_json_or_string,
9
+ )
10
+ from openai_cli.core.client import get_client
11
+ from openai_cli.core.exceptions import OpenAIError
12
+ from openai_cli.core.output import (
13
+ CHAT_MODELS,
14
+ DEFAULT_CHAT_MODEL,
15
+ print_chat_result,
16
+ print_error,
17
+ print_json,
18
+ )
19
+
20
+
21
+ @click.command()
22
+ @click.argument("prompt")
23
+ @click.option(
24
+ "-m",
25
+ "--model",
26
+ type=click.Choice(CHAT_MODELS),
27
+ default=DEFAULT_CHAT_MODEL,
28
+ show_default=True,
29
+ help="Model to use for chat completion.",
30
+ )
31
+ @click.option(
32
+ "-s",
33
+ "--system",
34
+ default=None,
35
+ help="System prompt to set the assistant's behavior.",
36
+ )
37
+ @click.option(
38
+ "--temperature",
39
+ default=None,
40
+ type=float,
41
+ help="Sampling temperature (0-2). Higher values = more random.",
42
+ )
43
+ @click.option(
44
+ "--max-tokens",
45
+ default=None,
46
+ type=int,
47
+ help="Maximum number of tokens to generate.",
48
+ )
49
+ @click.option(
50
+ "--max-completion-tokens",
51
+ default=None,
52
+ type=int,
53
+ help="Upper bound for tokens generated in a completion (including reasoning tokens).",
54
+ )
55
+ @click.option(
56
+ "-n",
57
+ "--count",
58
+ default=None,
59
+ type=int,
60
+ help="Number of completion choices to generate.",
61
+ )
62
+ @click.option(
63
+ "--top-p",
64
+ default=None,
65
+ type=float,
66
+ help="Nucleus sampling probability mass (0-1). Alternative to temperature.",
67
+ )
68
+ @click.option(
69
+ "--frequency-penalty",
70
+ default=None,
71
+ type=float,
72
+ help="Penalize tokens by their frequency in the text so far (-2.0 to 2.0).",
73
+ )
74
+ @click.option(
75
+ "--presence-penalty",
76
+ default=None,
77
+ type=float,
78
+ help="Penalize tokens that have already appeared in the text (-2.0 to 2.0).",
79
+ )
80
+ @click.option(
81
+ "--seed",
82
+ default=None,
83
+ type=int,
84
+ help="Seed for deterministic sampling.",
85
+ )
86
+ @click.option(
87
+ "--stop",
88
+ default=None,
89
+ multiple=True,
90
+ help="Stop sequence(s) where the API will stop generating (repeatable, up to 4).",
91
+ )
92
+ @click.option(
93
+ "--reasoning-effort",
94
+ type=click.Choice(["minimal", "low", "medium", "high"]),
95
+ default=None,
96
+ help="Reasoning effort for o1/o3/o4/gpt-5 series models.",
97
+ )
98
+ @click.option(
99
+ "--user",
100
+ default=None,
101
+ help="Unique end-user identifier for monitoring and abuse detection.",
102
+ )
103
+ @click.option(
104
+ "--service-tier",
105
+ type=click.Choice(["auto", "default", "flex", "scale", "priority"]),
106
+ default=None,
107
+ help="Processing type for serving the request (auto, default, flex, scale, priority).",
108
+ )
109
+ @click.option(
110
+ "--store",
111
+ is_flag=True,
112
+ default=False,
113
+ help="Store the output for use in OpenAI's model distillation or evals products.",
114
+ )
115
+ @click.option(
116
+ "--logprobs",
117
+ is_flag=True,
118
+ default=False,
119
+ help="Return log probabilities of the output tokens.",
120
+ )
121
+ @click.option(
122
+ "--top-logprobs",
123
+ default=None,
124
+ type=click.IntRange(0, 20),
125
+ help="Number of most likely tokens (0-20) to return at each token position with log probabilities.",
126
+ )
127
+ @click.option(
128
+ "--parallel-tool-calls",
129
+ "parallel_tool_calls",
130
+ flag_value=True,
131
+ default=None,
132
+ help="Enable parallel function calling during tool use.",
133
+ )
134
+ @click.option(
135
+ "--no-parallel-tool-calls",
136
+ "parallel_tool_calls",
137
+ flag_value=False,
138
+ help="Disable parallel function calling during tool use.",
139
+ )
140
+ @click.option(
141
+ "--stream", is_flag=True, default=False, help="Stream partial chat completion events."
142
+ )
143
+ @click.option(
144
+ "--response-format",
145
+ default=None,
146
+ help='Response format as JSON (e.g. \'{"type": "json_schema", "json_schema": {...}}\').',
147
+ )
148
+ @click.option(
149
+ "--tools",
150
+ default=None,
151
+ help='Tool definitions as a JSON array (e.g. \'[{"type":"function","function":{...}}]\').',
152
+ )
153
+ @click.option(
154
+ "--tool-choice",
155
+ default=None,
156
+ help='Tool selection mode or JSON object (e.g. "auto" or \'{"type":"function","function":{"name":"lookup"}}\').',
157
+ )
158
+ @click.option(
159
+ "--stream-options",
160
+ default=None,
161
+ help="Streaming options as a JSON object (e.g. '{\"include_usage\": true}').",
162
+ )
163
+ @click.option(
164
+ "--metadata",
165
+ default=None,
166
+ help="Metadata as a JSON object.",
167
+ )
168
+ @click.option(
169
+ "--logit-bias",
170
+ default=None,
171
+ help="Logit bias map as a JSON object.",
172
+ )
173
+ @click.option(
174
+ "--modalities",
175
+ default=None,
176
+ help="Requested modalities as a JSON array.",
177
+ )
178
+ @click.option(
179
+ "--audio",
180
+ default=None,
181
+ help="Audio output settings as a JSON object.",
182
+ )
183
+ @click.option(
184
+ "--prediction",
185
+ default=None,
186
+ help="Prediction settings as a JSON object.",
187
+ )
188
+ @click.option(
189
+ "--web-search-options",
190
+ default=None,
191
+ help="Web search settings as a JSON object.",
192
+ )
193
+ @click.option("--json", "output_json", is_flag=True, help="Output raw JSON.")
194
+ @click.pass_context
195
+ def chat(
196
+ ctx: click.Context,
197
+ prompt: str,
198
+ model: str,
199
+ system: str | None,
200
+ temperature: float | None,
201
+ max_tokens: int | None,
202
+ max_completion_tokens: int | None,
203
+ count: int | None,
204
+ top_p: float | None,
205
+ frequency_penalty: float | None,
206
+ presence_penalty: float | None,
207
+ seed: int | None,
208
+ stop: tuple[str, ...],
209
+ reasoning_effort: str | None,
210
+ user: str | None,
211
+ service_tier: str | None,
212
+ store: bool,
213
+ logprobs: bool,
214
+ top_logprobs: int | None,
215
+ parallel_tool_calls: bool | None,
216
+ stream: bool,
217
+ response_format: str | None,
218
+ tools: str | None,
219
+ tool_choice: str | None,
220
+ stream_options: str | None,
221
+ metadata: str | None,
222
+ logit_bias: str | None,
223
+ modalities: str | None,
224
+ audio: str | None,
225
+ prediction: str | None,
226
+ web_search_options: str | None,
227
+ output_json: bool,
228
+ ) -> None:
229
+ """Chat with an OpenAI-compatible model.
230
+
231
+ PROMPT is the user message to send to the model.
232
+
233
+ \b
234
+ Examples:
235
+ openai-cli chat "What is the capital of France?"
236
+ openai-cli chat "Explain quantum computing" -m gpt-5.4
237
+ openai-cli chat "Write a poem" -m gpt-4o --temperature 0.9
238
+ openai-cli chat "Summarize this" -s "You are a concise summarizer"
239
+ openai-cli chat "Reason about this" -m o3 --reasoning-effort high
240
+ """
241
+ client = get_client(ctx.obj.get("token"))
242
+ messages = []
243
+ if system:
244
+ messages.append({"role": "system", "content": system})
245
+ messages.append({"role": "user", "content": prompt})
246
+
247
+ try:
248
+ parsed_response_format = parse_json_object(response_format, "--response-format")
249
+ parsed_tools = parse_json_array(tools, "--tools")
250
+ parsed_tool_choice = parse_json_or_string(tool_choice, "--tool-choice")
251
+ parsed_stream_options = parse_json_object(stream_options, "--stream-options")
252
+ parsed_metadata = parse_json_object(metadata, "--metadata")
253
+ parsed_logit_bias = parse_json_object(logit_bias, "--logit-bias")
254
+ parsed_modalities = parse_json_array(modalities, "--modalities")
255
+ parsed_audio = parse_json_object(audio, "--audio")
256
+ parsed_prediction = parse_json_object(prediction, "--prediction")
257
+ parsed_web_search_options = parse_json_object(web_search_options, "--web-search-options")
258
+ except click.BadParameter as e:
259
+ print_error(e.format_message())
260
+ raise SystemExit(1) from None
261
+ payload: dict[str, object] = {
262
+ "model": model,
263
+ "messages": messages,
264
+ "stream": stream or None,
265
+ "temperature": temperature,
266
+ "max_tokens": max_tokens,
267
+ "max_completion_tokens": max_completion_tokens,
268
+ "n": count,
269
+ "response_format": parsed_response_format,
270
+ "tools": parsed_tools,
271
+ "tool_choice": parsed_tool_choice,
272
+ "top_p": top_p,
273
+ "frequency_penalty": frequency_penalty,
274
+ "presence_penalty": presence_penalty,
275
+ "seed": seed,
276
+ "stop": list(stop) if stop else None,
277
+ "stream_options": parsed_stream_options,
278
+ "reasoning_effort": reasoning_effort,
279
+ "user": user,
280
+ "service_tier": service_tier,
281
+ "store": store if store else None,
282
+ "metadata": parsed_metadata,
283
+ "logit_bias": parsed_logit_bias,
284
+ "logprobs": logprobs if logprobs else None,
285
+ "top_logprobs": top_logprobs,
286
+ "parallel_tool_calls": parallel_tool_calls,
287
+ "modalities": parsed_modalities,
288
+ "audio": parsed_audio,
289
+ "prediction": parsed_prediction,
290
+ "web_search_options": parsed_web_search_options,
291
+ }
292
+
293
+ try:
294
+ result = client.chat_completions(**payload) # type: ignore[arg-type]
295
+ if output_json:
296
+ print_json(result)
297
+ else:
298
+ print_chat_result(result)
299
+ except OpenAIError as e:
300
+ print_error(e.message)
301
+ raise SystemExit(1) from e