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 ADDED
@@ -0,0 +1,3 @@
1
+ """OpenAI CLI - Command-line tool for OpenAI-compatible APIs via AceDataCloud."""
2
+
3
+ __version__ = "0.1.0"
openai_cli/__main__.py ADDED
@@ -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
@@ -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