ostruct-cli 0.8.3__py3-none-any.whl → 0.8.7__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.
ostruct/cli/cli.py CHANGED
@@ -4,6 +4,7 @@ import sys
4
4
  from typing import Optional
5
5
 
6
6
  import click
7
+ from dotenv import load_dotenv
7
8
 
8
9
  from .. import __version__
9
10
  from .commands import create_command_group
@@ -107,6 +108,9 @@ def create_cli() -> click.Command:
107
108
 
108
109
  def main() -> None:
109
110
  """Main entry point for the CLI."""
111
+ # Load environment variables from .env file
112
+ load_dotenv()
113
+
110
114
  try:
111
115
  cli(standalone_mode=False)
112
116
  except (
@@ -492,12 +492,13 @@ def api_options(f: Union[Command, Callable[..., Any]]) -> Command:
492
492
  environment variable.""",
493
493
  )(cmd)
494
494
 
495
+ # API timeout for OpenAI calls
495
496
  cmd = click.option(
496
497
  "--timeout",
497
498
  type=click.FloatRange(1.0, None),
498
499
  default=60.0,
499
500
  show_default=True,
500
- help="API timeout in seconds.",
501
+ help="Timeout in seconds for OpenAI API calls.",
501
502
  )(cmd)
502
503
 
503
504
  return cast(Command, cmd)
@@ -854,13 +855,6 @@ def debug_progress_options(f: Union[Command, Callable[..., Any]]) -> Command:
854
855
  "--verbose", is_flag=True, help="Enable verbose logging"
855
856
  )(cmd)
856
857
 
857
- cmd = click.option(
858
- "--timeout",
859
- type=int,
860
- default=3600,
861
- help="Operation timeout in seconds (default: 3600 = 1 hour)",
862
- )(cmd)
863
-
864
858
  return cast(Command, cmd)
865
859
 
866
860
 
ostruct/cli/runner.py CHANGED
@@ -33,9 +33,6 @@ from .sentinel import extract_json_block
33
33
  from .serialization import LogSerializer
34
34
  from .services import ServiceContainer
35
35
  from .types import CLIParams
36
- from .unattended_operation import (
37
- UnattendedOperationManager,
38
- )
39
36
 
40
37
 
41
38
  # Error classes for API operations
@@ -855,10 +852,6 @@ async def execute_model(
855
852
  """Execute the model with the given parameters."""
856
853
  logger.debug("=== Execution Phase ===")
857
854
 
858
- # Initialize unattended operation manager
859
- timeout_seconds = int(args.get("timeout", 3600))
860
- operation_manager = UnattendedOperationManager(timeout_seconds)
861
-
862
855
  # Pre-validate unattended compatibility
863
856
  # Note: MCP validation is handled during MCP configuration processing
864
857
  # mcp_servers = args.get("mcp_servers", [])
@@ -874,12 +867,22 @@ async def execute_model(
874
867
 
875
868
  api_key = args.get("api_key") or os.getenv("OPENAI_API_KEY")
876
869
  if not api_key:
877
- msg = "No API key provided. Set OPENAI_API_KEY environment variable or use --api-key"
870
+ msg = (
871
+ "No OpenAI API key found. Please:\n"
872
+ " • Set OPENAI_API_KEY environment variable, or\n"
873
+ " • Create a .env file with OPENAI_API_KEY=your-key-here, or\n"
874
+ " • Use --api-key option (not recommended for production)\n"
875
+ "\n"
876
+ "Get your API key from: https://platform.openai.com/api-keys"
877
+ )
878
878
  logger.error(msg)
879
879
  raise CLIError(msg, exit_code=ExitCode.API_ERROR)
880
880
 
881
+ # Get API timeout
882
+ api_timeout = args.get("timeout", 60.0)
881
883
  client = AsyncOpenAI(
882
- api_key=api_key, timeout=min(args.get("timeout", 60.0), 300.0)
884
+ api_key=api_key,
885
+ timeout=min(float(api_timeout), 300.0),
883
886
  ) # Cap at 5 min for client timeout
884
887
 
885
888
  # Create service container for dependency management
@@ -1352,13 +1355,10 @@ async def execute_model(
1352
1355
 
1353
1356
  return ExitCode.SUCCESS
1354
1357
 
1355
- # Execute main operation with timeout safeguards
1358
+ # Execute main operation
1356
1359
  try:
1357
- result = await operation_manager.execute_with_safeguards(
1358
- execute_main_operation, "model execution"
1359
- )
1360
- # The result should be an ExitCode from execute_main_operation
1361
- return result # type: ignore[no-any-return]
1360
+ result = await execute_main_operation()
1361
+ return result
1362
1362
  except (
1363
1363
  APIResponseError,
1364
1364
  EmptyResponseError,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: ostruct-cli
3
- Version: 0.8.3
3
+ Version: 0.8.7
4
4
  Summary: CLI for OpenAI Structured Output with Multi-Tool Integration
5
5
  Author: Yaniv Golan
6
6
  Author-email: yaniv@golan.name
@@ -39,6 +39,7 @@ Requires-Dist: pytest (>=8.3.4,<9.0) ; extra == "dev"
39
39
  Requires-Dist: pytest-asyncio (>=0.25.2,<1.0) ; extra == "dev"
40
40
  Requires-Dist: pytest-mock (>=3.14.0,<4.0) ; extra == "dev"
41
41
  Requires-Dist: pytest-rerunfailures (>=12.0,<13.0) ; extra == "dev"
42
+ Requires-Dist: python-dotenv (>=1.0.1,<2.0)
42
43
  Requires-Dist: python-dotenv (>=1.0.1,<2.0) ; extra == "dev"
43
44
  Requires-Dist: pyyaml (>=6.0.2,<7.0)
44
45
  Requires-Dist: sphinx (>=7.0,<8.0) ; extra == "dev"
@@ -48,6 +49,7 @@ Requires-Dist: sphinx-rtd-theme (>=1.0,<2.0) ; extra == "docs"
48
49
  Requires-Dist: tenacity (>=8.2.3,<9.0) ; extra == "examples"
49
50
  Requires-Dist: tiktoken (==0.9.0)
50
51
  Requires-Dist: tomli (>=2.0.1,<3.0) ; (python_version < "3.11") and (extra == "docs")
52
+ Requires-Dist: tomli (>=2.0.1,<3.0) ; extra == "dev"
51
53
  Requires-Dist: tomli (>=2.0.1,<3.0) ; python_version < "3.11"
52
54
  Requires-Dist: twine (>=6.0.1,<7.0) ; extra == "dev"
53
55
  Requires-Dist: types-cachetools (>=5.5.0.20240820) ; extra == "dev"
@@ -214,7 +216,27 @@ Break down words into their components, showing their origins, meanings, and hie
214
216
 
215
217
  ## Installation
216
218
 
217
- ### For Users
219
+ ### Quick Install (macOS)
220
+
221
+ For macOS users, we provide a one-line installer that handles everything automatically:
222
+
223
+ ```bash
224
+ curl -sSL https://raw.githubusercontent.com/yaniv-golan/ostruct/main/scripts/install-macos.sh | bash
225
+ ```
226
+
227
+ This script will:
228
+
229
+ - Install Python 3.10+ if needed (via Homebrew or python.org)
230
+ - Install Homebrew if needed
231
+ - Install ostruct-cli via pip
232
+ - Configure your shell PATH automatically
233
+ - Verify the installation works
234
+
235
+ After installation, restart your terminal and test with `ostruct --version`.
236
+
237
+ ### Manual Installation
238
+
239
+ #### For Users
218
240
 
219
241
  To install the latest stable version from PyPI:
220
242
 
@@ -222,7 +244,9 @@ To install the latest stable version from PyPI:
222
244
  pip install ostruct-cli
223
245
  ```
224
246
 
225
- ### For Developers
247
+ **Note**: If the `ostruct` command isn't found after installation, you may need to add Python's user bin directory to your PATH. See the [troubleshooting guide](scripts/README.md#troubleshooting) for details.
248
+
249
+ #### For Developers
226
250
 
227
251
  If you plan to contribute to the project, see the [Development Setup](#development-setup) section below for instructions on setting up the development environment with Poetry.
228
252
 
@@ -237,6 +261,8 @@ ostruct-cli respects the following environment variables:
237
261
  - `OSTRUCT_DISABLE_REGISTRY_UPDATE_CHECKS`: Set to "1", "true", or "yes" to disable automatic registry update checks
238
262
  - `MCP_<NAME>_URL`: Custom MCP server URLs (e.g., `MCP_STRIPE_URL=https://mcp.stripe.com`)
239
263
 
264
+ **💡 Tip**: ostruct automatically loads `.env` files from the current directory. Environment variables take precedence over `.env` file values.
265
+
240
266
  <details>
241
267
  <summary><strong>Shell Completion Setup</strong> (Click to expand)</summary>
242
268
 
@@ -427,7 +453,11 @@ tools:
427
453
  1. Set your OpenAI API key:
428
454
 
429
455
  ```bash
456
+ # Environment variable
430
457
  export OPENAI_API_KEY=your-api-key
458
+
459
+ # Or create a .env file
460
+ echo 'OPENAI_API_KEY=your-api-key' > .env
431
461
  ```
432
462
 
433
463
  ### Example 1: Basic Text Extraction (Simplest)
@@ -2,8 +2,8 @@ ostruct/__init__.py,sha256=X6zo6V7ZNMv731Wi388aTVQngD1410ExGwGx4J6lpyo,187
2
2
  ostruct/cli/__init__.py,sha256=e-DtWRviCr3fIAJH4cB4UAvles3-rqnhJaTOlBn9TKs,871
3
3
  ostruct/cli/base_errors.py,sha256=o-877bJJA8yJWISRPy0KyL6wDu1-_avddmQIfVePuFM,5989
4
4
  ostruct/cli/cache_manager.py,sha256=ej3KrRfkKKZ_lEp2JswjbJ5bW2ncsvna9NeJu81cqqs,5192
5
- ostruct/cli/cli.py,sha256=ZUkQ-iwk4KCKeetPMlvSDwxfXIe4h1-yP80SfJgvi_o,4098
6
- ostruct/cli/click_options.py,sha256=FbRMfoFgg5icdgewPS8cePSYv6yTnxbRxyDvfFDdRaI,31845
5
+ ostruct/cli/cli.py,sha256=pzOzKMvWQMRS1I9w4raAUi-O7IN6OKViNTcOeJGEqhI,4196
6
+ ostruct/cli/click_options.py,sha256=UWLBIkfVMXcIMXInJFWNYNO9Ieg8YrJEzRfkKungy48,31730
7
7
  ostruct/cli/code_interpreter.py,sha256=lnnyEvUh2pGObN9ENpr-X4p0C0oIWiyG1CFQWW4akBQ,16726
8
8
  ostruct/cli/commands/__init__.py,sha256=3NHz-WZ9XqrnWWMksoV2MpYpHnjA-EO9lsrBOYeHcjY,723
9
9
  ostruct/cli/commands/list_models.py,sha256=yeuQpUGAmRr4uOHS7teuVHkC9dkqN0yKDOEw_n-ehi0,4662
@@ -28,7 +28,7 @@ ostruct/cli/path_utils.py,sha256=j44q1OoLkqMErgK-qEuhuIZ1VyzqRIvNgxR1et9PoXA,481
28
28
  ostruct/cli/progress.py,sha256=rj9nVEco5UeZORMbzd7mFJpFGJjbH9KbBFh5oTE5Anw,3415
29
29
  ostruct/cli/progress_reporting.py,sha256=MBjALM4pmPd_d9YuXqH162-tkC6DDKYmz-pJPSGLTfk,13669
30
30
  ostruct/cli/registry_updates.py,sha256=ohiHdlfrocvThpR_ZjMyqulDKFjRM1hIFKOlNzpaqHg,5138
31
- ostruct/cli/runner.py,sha256=_xiT9_ywk5lNz3P1qFpqOcJGwXqAE4xQ8Zxc9p6x0Ko,65192
31
+ ostruct/cli/runner.py,sha256=GzCsPiwhxiaoXvCv-ykFO8KucMvGRyIOPuaNMCVF1pw,65107
32
32
  ostruct/cli/schema_utils.py,sha256=9LnsjxEKg6RIfXQB3nS3pyDggm5n-4-thXf92897gJU,3590
33
33
  ostruct/cli/schema_validation.py,sha256=ohEuxJ0KF93qphj0JSZDnrxDn0C2ZU37g-U2JY03onM,8154
34
34
  ostruct/cli/security/__init__.py,sha256=CQpkCgTFYlA1p6atpQeNgIKtE4LZGUKt4EbytbGKpCs,846
@@ -64,8 +64,8 @@ ostruct/cli/unattended_operation.py,sha256=kI95SSVJC_taxORXQYrce_qLEnuKc6edwn9tM
64
64
  ostruct/cli/utils.py,sha256=uY7c0NaINHWfnl77FcPE3TmYUXv3RqEeUTjrCMDij9A,922
65
65
  ostruct/cli/validators.py,sha256=lbxAUUVS5TPJ7HdYZ5yB7gUjJqfcClZCuh0oktoq0E0,15291
66
66
  ostruct/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
- ostruct_cli-0.8.3.dist-info/LICENSE,sha256=DmGAkaYzhrdzTB9Y2Rvfzd3mJiF9ZrTOhxN8t6wrfHA,1098
68
- ostruct_cli-0.8.3.dist-info/METADATA,sha256=mBsqO645XWKto3RgifluCxqkilYH0C14wWrm1Pa6P6I,24827
69
- ostruct_cli-0.8.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
70
- ostruct_cli-0.8.3.dist-info/entry_points.txt,sha256=NFq9IuqHVTem0j9zKjV8C1si_zGcP1RL6Wbvt9fUDXw,48
71
- ostruct_cli-0.8.3.dist-info/RECORD,,
67
+ ostruct_cli-0.8.7.dist-info/LICENSE,sha256=DmGAkaYzhrdzTB9Y2Rvfzd3mJiF9ZrTOhxN8t6wrfHA,1098
68
+ ostruct_cli-0.8.7.dist-info/METADATA,sha256=_vbhuslg4oHtPOrbin1om-82TA8E9K8IPoDlU84gm48,25921
69
+ ostruct_cli-0.8.7.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
70
+ ostruct_cli-0.8.7.dist-info/entry_points.txt,sha256=NFq9IuqHVTem0j9zKjV8C1si_zGcP1RL6Wbvt9fUDXw,48
71
+ ostruct_cli-0.8.7.dist-info/RECORD,,