ostruct-cli 0.8.8__py3-none-any.whl → 1.0.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.
Files changed (50) hide show
  1. ostruct/cli/__init__.py +3 -15
  2. ostruct/cli/attachment_processor.py +455 -0
  3. ostruct/cli/attachment_template_bridge.py +973 -0
  4. ostruct/cli/cli.py +187 -33
  5. ostruct/cli/click_options.py +775 -692
  6. ostruct/cli/code_interpreter.py +195 -12
  7. ostruct/cli/commands/__init__.py +0 -3
  8. ostruct/cli/commands/run.py +289 -62
  9. ostruct/cli/config.py +23 -22
  10. ostruct/cli/constants.py +89 -0
  11. ostruct/cli/errors.py +191 -6
  12. ostruct/cli/explicit_file_processor.py +0 -15
  13. ostruct/cli/file_info.py +118 -14
  14. ostruct/cli/file_list.py +82 -1
  15. ostruct/cli/file_search.py +68 -2
  16. ostruct/cli/help_json.py +235 -0
  17. ostruct/cli/mcp_integration.py +13 -16
  18. ostruct/cli/params.py +217 -0
  19. ostruct/cli/plan_assembly.py +335 -0
  20. ostruct/cli/plan_printing.py +385 -0
  21. ostruct/cli/progress_reporting.py +8 -56
  22. ostruct/cli/quick_ref_help.py +128 -0
  23. ostruct/cli/rich_config.py +299 -0
  24. ostruct/cli/runner.py +397 -190
  25. ostruct/cli/security/__init__.py +2 -0
  26. ostruct/cli/security/allowed_checker.py +41 -0
  27. ostruct/cli/security/normalization.py +13 -9
  28. ostruct/cli/security/security_manager.py +558 -17
  29. ostruct/cli/security/types.py +15 -0
  30. ostruct/cli/template_debug.py +283 -261
  31. ostruct/cli/template_debug_help.py +233 -142
  32. ostruct/cli/template_env.py +46 -5
  33. ostruct/cli/template_filters.py +415 -8
  34. ostruct/cli/template_processor.py +240 -619
  35. ostruct/cli/template_rendering.py +49 -73
  36. ostruct/cli/template_validation.py +2 -1
  37. ostruct/cli/token_validation.py +35 -15
  38. ostruct/cli/types.py +15 -19
  39. ostruct/cli/unicode_compat.py +283 -0
  40. ostruct/cli/upload_manager.py +448 -0
  41. ostruct/cli/utils.py +30 -0
  42. ostruct/cli/validators.py +272 -54
  43. {ostruct_cli-0.8.8.dist-info → ostruct_cli-1.0.0.dist-info}/METADATA +292 -126
  44. ostruct_cli-1.0.0.dist-info/RECORD +80 -0
  45. ostruct/cli/commands/quick_ref.py +0 -54
  46. ostruct/cli/template_optimizer.py +0 -478
  47. ostruct_cli-0.8.8.dist-info/RECORD +0 -71
  48. {ostruct_cli-0.8.8.dist-info → ostruct_cli-1.0.0.dist-info}/LICENSE +0 -0
  49. {ostruct_cli-0.8.8.dist-info → ostruct_cli-1.0.0.dist-info}/WHEEL +0 -0
  50. {ostruct_cli-0.8.8.dist-info → ostruct_cli-1.0.0.dist-info}/entry_points.txt +0 -0
ostruct/cli/cli.py CHANGED
@@ -1,9 +1,11 @@
1
- """Minimal CLI entry point for ostruct."""
1
+ #!/usr/bin/env python3
2
+ """Main CLI module for ostruct."""
2
3
 
4
+ import os
3
5
  import sys
4
6
  from typing import Optional
5
7
 
6
- import click
8
+ import rich_click as click
7
9
  from dotenv import load_dotenv
8
10
 
9
11
  from .. import __version__
@@ -17,50 +19,119 @@ from .errors import (
17
19
  handle_error,
18
20
  )
19
21
  from .exit_codes import ExitCode
22
+ from .help_json import print_full_cli_help_json as print_full_help_json
20
23
  from .registry_updates import get_update_notification
21
24
 
25
+ # Import rich-click configuration
26
+ from .rich_config import * # noqa: F401,F403
27
+ from .unicode_compat import safe_emoji
28
+ from .utils import fix_surrogate_escapes
29
+
30
+ # Load environment variables from .env file
31
+ load_dotenv()
32
+
33
+
34
+ def _handle_quick_ref(
35
+ ctx: click.Context, param: click.Parameter, value: bool
36
+ ) -> None:
37
+ """Handle --quick-ref flag by showing quick reference help and exiting."""
38
+ if not value or ctx.resilient_parsing:
39
+ return
40
+
41
+ from .quick_ref_help import show_quick_ref_help
42
+
43
+ show_quick_ref_help()
44
+ ctx.exit()
45
+
46
+
47
+ def _handle_version(
48
+ ctx: click.Context, param: click.Parameter, value: bool
49
+ ) -> None:
50
+ """Handle --version flag by showing version and exiting."""
51
+ if not value or ctx.resilient_parsing:
52
+ return
53
+ click.echo(f"ostruct, version {__version__}")
54
+ ctx.exit()
55
+
56
+
57
+ def fix_argv_encoding() -> None:
58
+ """Fix UTF-8 encoding issues in sys.argv.
59
+
60
+ This function addresses the surrogate escape issue where Python's sys.argv
61
+ contains surrogate characters (e.g., a backslash followed by 'udce2')
62
+ when processing command line arguments with non-ASCII characters. This
63
+ commonly happens with filenames containing characters like en dash (–) or
64
+ other Unicode characters.
65
+
66
+ The fix detects arguments containing surrogate escapes and converts them
67
+ back to proper UTF-8 strings.
68
+ """
69
+ try:
70
+ fixed_argv = []
71
+ for arg in sys.argv:
72
+ fixed_argv.append(fix_surrogate_escapes(arg))
73
+
74
+ # Replace sys.argv with the fixed version
75
+ sys.argv = fixed_argv
76
+
77
+ except Exception:
78
+ # If anything goes wrong with the encoding fix, continue with original argv
79
+ # This ensures the CLI doesn't break even if the fix fails
80
+ pass
81
+
22
82
 
23
83
  def create_cli_group() -> click.Group:
24
84
  """Create the main CLI group with all commands."""
25
85
 
26
- @click.group()
27
- @click.version_option(version=__version__)
86
+ @click.group(cls=click.RichGroup)
87
+ @click.option(
88
+ "--version",
89
+ "-V",
90
+ is_flag=True,
91
+ expose_value=False,
92
+ is_eager=True,
93
+ callback=_handle_version,
94
+ help="Show the version and exit.",
95
+ )
28
96
  @click.option(
29
97
  "--config",
30
98
  type=click.Path(exists=True),
31
99
  help="Configuration file path (default: ostruct.yaml)",
32
100
  )
101
+ @click.option(
102
+ "--quick-ref",
103
+ is_flag=True,
104
+ callback=_handle_quick_ref,
105
+ expose_value=False,
106
+ is_eager=True,
107
+ help=f"{safe_emoji('📖')} Show concise usage examples and patterns",
108
+ )
109
+ @click.option(
110
+ "--help-json",
111
+ is_flag=True,
112
+ callback=print_full_help_json,
113
+ expose_value=False,
114
+ is_eager=True,
115
+ hidden=True, # Hide from help output - feature not ready for release
116
+ help=f"{safe_emoji('📖')} Output comprehensive help for all commands in JSON format",
117
+ )
118
+ @click.option(
119
+ "--unicode/--no-unicode",
120
+ default=None,
121
+ help="Force enable/disable Unicode emoji display (overrides auto-detection)",
122
+ envvar="OSTRUCT_UNICODE",
123
+ )
33
124
  @click.pass_context
34
- def cli_group(ctx: click.Context, config: Optional[str] = None) -> None:
35
- """ostruct - AI-powered structured output with multi-tool integration.
36
-
37
- ostruct transforms unstructured inputs into structured JSON using OpenAI APIs,
38
- Jinja2 templates, and powerful tool integrations including Code Interpreter,
39
- File Search, Web Search, and MCP servers.
40
-
41
- 🚀 QUICK START:
42
- ostruct run template.j2 schema.json -V name=value
43
-
44
- 📁 FILE ROUTING (explicit tool assignment):
45
- -ft/--file-for-template Template access only
46
- -fc/--file-for-code-interpreter Code execution & analysis
47
- -fs/--file-for-file-search Document search & retrieval
48
-
49
- ⚡ EXAMPLES:
50
- # Basic usage (unchanged)
51
- ostruct run template.j2 schema.json -f config.yaml
52
-
53
- # Multi-tool explicit routing
54
- ostruct run analysis.j2 schema.json -fc data.csv -fs docs.pdf -ft config.yaml
55
-
56
- # Advanced routing with --file-for
57
- ostruct run task.j2 schema.json --file-for code-interpreter shared.json --file-for file-search shared.json
125
+ def cli_group(
126
+ ctx: click.Context,
127
+ config: Optional[str] = None,
128
+ unicode: Optional[bool] = None,
129
+ ) -> None:
130
+ """ostruct - AI-powered structured output with multi-tool integration."""
131
+ # Handle Unicode preference
132
+ if unicode is not None:
133
+ os.environ["OSTRUCT_UNICODE"] = "1" if unicode else "0"
58
134
 
59
- # MCP server integration
60
- ostruct run template.j2 schema.json --mcp-server deepwiki@https://mcp.deepwiki.com/sse
61
-
62
- 📖 For detailed documentation: https://ostruct.readthedocs.io
63
- """
64
135
  # Load configuration
65
136
  try:
66
137
  app_config = OstructConfig.load(config)
@@ -85,6 +156,86 @@ def create_cli_group() -> click.Group:
85
156
  # Ensure any errors don't affect normal operation
86
157
  pass
87
158
 
159
+ # Set the docstring dynamically with emoji compatibility
160
+ rocket = safe_emoji("🚀")
161
+ folder = safe_emoji("📁")
162
+ target = safe_emoji("🎯")
163
+ book = safe_emoji("📖")
164
+ lightning = safe_emoji("⚡")
165
+ wrench = safe_emoji("🔧")
166
+
167
+ cli_group.__doc__ = f"""ostruct - AI-powered structured output with multi-tool integration.
168
+
169
+ Transform unstructured inputs into structured JSON using OpenAI APIs, Jinja2 templates, and powerful tool integrations.
170
+
171
+ {rocket} **QUICK START**
172
+
173
+ ostruct run template.j2 schema.json --var name=value
174
+
175
+ {folder} **FILE ATTACHMENT SYSTEM**
176
+
177
+ --file [targets:]alias path Attach file with optional target routing
178
+
179
+ --dir [targets:]alias path Attach directory with optional target routing
180
+
181
+ {target} **TARGETS**
182
+
183
+ prompt (default) Template access only
184
+
185
+ code-interpreter, ci Code execution & analysis
186
+
187
+ file-search, fs Document search & retrieval
188
+
189
+ {book} **GETTING HELP**
190
+
191
+ ostruct --help Command overview
192
+
193
+ ostruct --quick-ref Usage examples and patterns
194
+
195
+ ostruct run --help Detailed options reference
196
+
197
+ ostruct run --help-debug Troubleshooting guide
198
+
199
+ {book} Documentation: https://ostruct.readthedocs.io
200
+
201
+ {lightning} **EXAMPLES**
202
+
203
+ # Basic usage
204
+ ostruct run template.j2 schema.json --file data file.txt
205
+
206
+ # Multi-tool routing
207
+ ostruct run analysis.j2 schema.json --file ci:data data.csv --file fs:docs manual.pdf
208
+
209
+ # Combined targets
210
+ ostruct run task.j2 schema.json --file ci,fs:shared data.json
211
+
212
+ # MCP server integration
213
+ ostruct run template.j2 schema.json --mcp-server deepwiki@https://mcp.deepwiki.com/sse
214
+
215
+ {wrench} **ENVIRONMENT VARIABLES**
216
+
217
+ ```text
218
+ Core API Configuration:
219
+ OPENAI_API_KEY OpenAI API authentication key
220
+ OPENAI_API_BASE Custom OpenAI API base URL
221
+
222
+ Template Processing Limits:
223
+ OSTRUCT_TEMPLATE_FILE_LIMIT Max individual file size (default: 64KB)
224
+ OSTRUCT_TEMPLATE_TOTAL_LIMIT Max total files size (default: 1MB)
225
+ OSTRUCT_TEMPLATE_PREVIEW_LIMIT Template preview size limit (default: 4096)
226
+
227
+ System Behavior:
228
+ OSTRUCT_DISABLE_REGISTRY_UPDATE_CHECKS Disable model registry updates
229
+ OSTRUCT_MCP_URL_<name> Custom MCP server URLs
230
+
231
+ Unicode Display Control:
232
+ OSTRUCT_UNICODE=auto Auto-detect terminal capabilities (default)
233
+ OSTRUCT_UNICODE=1/true/yes Force emoji display (override detection)
234
+ OSTRUCT_UNICODE=0/false/no Force plain text (override detection)
235
+ OSTRUCT_UNICODE=debug Show detection details and auto-detect
236
+ ```
237
+ """
238
+
88
239
  # Add all commands from the command module
89
240
  command_group = create_command_group()
90
241
  for command in command_group.commands.values():
@@ -108,6 +259,9 @@ def create_cli() -> click.Command:
108
259
 
109
260
  def main() -> None:
110
261
  """Main entry point for the CLI."""
262
+ # Fix UTF-8 encoding issues in command line arguments before processing
263
+ fix_argv_encoding()
264
+
111
265
  # Load environment variables from .env file
112
266
  load_dotenv()
113
267