openai-pro-cli 2026.8.11.0__py3-none-any.whl
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.
- openai_cli/__init__.py +3 -0
- openai_cli/__main__.py +6 -0
- openai_cli/commands/__init__.py +1 -0
- openai_cli/commands/_json.py +46 -0
- openai_cli/commands/chat.py +301 -0
- openai_cli/commands/embed.py +78 -0
- openai_cli/commands/image.py +323 -0
- openai_cli/commands/info.py +45 -0
- openai_cli/commands/realtime.py +64 -0
- openai_cli/commands/response.py +115 -0
- openai_cli/commands/speech.py +100 -0
- openai_cli/commands/tasks.py +136 -0
- openai_cli/commands/transcribe.py +124 -0
- openai_cli/core/__init__.py +1 -0
- openai_cli/core/client.py +281 -0
- openai_cli/core/config.py +39 -0
- openai_cli/core/exceptions.py +37 -0
- openai_cli/core/output.py +466 -0
- openai_cli/main.py +86 -0
- openai_pro_cli-2026.8.11.0.dist-info/METADATA +144 -0
- openai_pro_cli-2026.8.11.0.dist-info/RECORD +24 -0
- openai_pro_cli-2026.8.11.0.dist-info/WHEEL +4 -0
- openai_pro_cli-2026.8.11.0.dist-info/entry_points.txt +2 -0
- openai_pro_cli-2026.8.11.0.dist-info/licenses/LICENSE +21 -0
openai_cli/__init__.py
ADDED
openai_cli/__main__.py
ADDED
|
@@ -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
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""Text embedding command."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from openai_cli.core.client import get_client
|
|
6
|
+
from openai_cli.core.exceptions import OpenAIError
|
|
7
|
+
from openai_cli.core.output import (
|
|
8
|
+
DEFAULT_EMBEDDING_MODEL,
|
|
9
|
+
EMBEDDING_MODELS,
|
|
10
|
+
print_embedding_result,
|
|
11
|
+
print_error,
|
|
12
|
+
print_json,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@click.command()
|
|
17
|
+
@click.argument("text", nargs=-1, required=True)
|
|
18
|
+
@click.option(
|
|
19
|
+
"-m",
|
|
20
|
+
"--model",
|
|
21
|
+
type=click.Choice(EMBEDDING_MODELS),
|
|
22
|
+
default=DEFAULT_EMBEDDING_MODEL,
|
|
23
|
+
show_default=True,
|
|
24
|
+
help="Embedding model to use.",
|
|
25
|
+
)
|
|
26
|
+
@click.option(
|
|
27
|
+
"--encoding-format",
|
|
28
|
+
type=click.Choice(["float", "base64"]),
|
|
29
|
+
default="float",
|
|
30
|
+
show_default=True,
|
|
31
|
+
help="Format of the returned embeddings.",
|
|
32
|
+
)
|
|
33
|
+
@click.option(
|
|
34
|
+
"--dimensions",
|
|
35
|
+
default=None,
|
|
36
|
+
type=int,
|
|
37
|
+
help="Output embedding size (when supported by the model).",
|
|
38
|
+
)
|
|
39
|
+
@click.option("--json", "output_json", is_flag=True, help="Output raw JSON.")
|
|
40
|
+
@click.pass_context
|
|
41
|
+
def embed(
|
|
42
|
+
ctx: click.Context,
|
|
43
|
+
text: tuple[str, ...],
|
|
44
|
+
model: str,
|
|
45
|
+
encoding_format: str,
|
|
46
|
+
dimensions: int | None,
|
|
47
|
+
output_json: bool,
|
|
48
|
+
) -> None:
|
|
49
|
+
"""Generate text embeddings.
|
|
50
|
+
|
|
51
|
+
TEXT is the input string(s) to embed. Pass multiple TEXT arguments to
|
|
52
|
+
embed a batch of inputs in a single request.
|
|
53
|
+
|
|
54
|
+
\b
|
|
55
|
+
Examples:
|
|
56
|
+
openai-cli embed "Hello, world!"
|
|
57
|
+
openai-cli embed "Semantic search query" -m text-embedding-3-large
|
|
58
|
+
openai-cli embed "Document text" --dimensions 256
|
|
59
|
+
openai-cli embed "First text" "Second text" "Third text"
|
|
60
|
+
"""
|
|
61
|
+
client = get_client(ctx.obj.get("token"))
|
|
62
|
+
input_value: str | list[str] = text[0] if len(text) == 1 else list(text)
|
|
63
|
+
payload: dict[str, object] = {
|
|
64
|
+
"model": model,
|
|
65
|
+
"input": input_value,
|
|
66
|
+
"encoding_format": encoding_format,
|
|
67
|
+
"dimensions": dimensions,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
result = client.embeddings(**payload) # type: ignore[arg-type]
|
|
72
|
+
if output_json:
|
|
73
|
+
print_json(result)
|
|
74
|
+
else:
|
|
75
|
+
print_embedding_result(result)
|
|
76
|
+
except OpenAIError as e:
|
|
77
|
+
print_error(e.message)
|
|
78
|
+
raise SystemExit(1) from e
|