hexastack-cli 0.8.0__tar.gz → 0.10.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 (26) hide show
  1. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/PKG-INFO +60 -3
  2. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/README.md +59 -2
  3. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/pyproject.toml +2 -2
  4. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/pyproject.toml.orig +2 -2
  5. hexastack_cli-0.10.0/src/hexastack_cli/adapters/__init__.py +25 -0
  6. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/adapters/routing.py +6 -2
  7. hexastack_cli-0.10.0/src/hexastack_cli/adapters/suggest.py +417 -0
  8. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/infra/app.py +2 -1
  9. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/infra/autodiscovery.py +35 -11
  10. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/infra/decorators.py +15 -2
  11. hexastack_cli-0.10.0/src/hexastack_cli/testing/narrator.py +323 -0
  12. hexastack_cli-0.8.0/src/hexastack_cli/adapters/__init__.py +0 -11
  13. hexastack_cli-0.8.0/src/hexastack_cli/testing/narrator.py +0 -188
  14. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/__init__.py +0 -0
  15. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/adapters/presenter.py +0 -0
  16. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/domain/__init__.py +0 -0
  17. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/domain/config.py +0 -0
  18. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/domain/options.py +0 -0
  19. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/infra/__init__.py +0 -0
  20. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/infra/bootstrap.py +0 -0
  21. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/infra/config.py +0 -0
  22. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/infra/options.py +0 -0
  23. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/py.typed +0 -0
  24. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/testing/__init__.py +0 -0
  25. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/testing/events.py +0 -0
  26. {hexastack_cli-0.8.0 → hexastack_cli-0.10.0}/src/hexastack_cli/testing/terminal.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hexastack-cli
3
- Version: 0.8.0
3
+ Version: 0.10.0
4
4
  Summary: Hexastack CLI presentation adapter with Typer and Rich
5
5
  Author: Richard West
6
6
  Author-email: Richard West <dopplereffect.us@gmail.com>
@@ -37,9 +37,11 @@ Description-Content-Type: text/markdown
37
37
 
38
38
  - **Nested Command Hierarchies**: Nest subcommands naturally (`app user create`, `app db migrate`) using `@cli_group`.
39
39
  - **Command Aliases**: Register multiple aliases for the same action (`app user new == app user create`).
40
+ - **Typo Tolerance & Suggestions (`TyperSuggest`)**: Drop-in replacement for `typer.Typer` that intercepts unrecognized subcommands or flags, computes closest matches via Levenshtein distance, prompts interactively for confirmation, and exits cleanly in CI/non-interactive pipelines.
40
41
  - **Feature Flag Gating**: Gate CLI commands dynamically with `@feature_flag_command(...)` and `@cli_command(..., feature_flag=...)`.
41
42
  - **Rich Formatted & CI-Friendly Output**: Beautiful tables, panels, and spinners for interactive terminals; clean text/JSON streaming for CI/CD pipelines.
42
43
  - **Direct CQRS Dispatching**: Declaratively expose domain commands (`@cli_command`) and queries (`@cli_query`) with automatic parameter parsing and validation.
44
+ - **Automated Demo Narration & Slicing (`CliNarrator`)**: Headless terminal recording generating asciinema streams, high-resolution `.webm` videos, chapterized `.checkpoint_segment()` flushes, and synchronized `.vtt` subtitles.
43
45
 
44
46
  ---
45
47
 
@@ -48,7 +50,8 @@ Description-Content-Type: text/markdown
48
50
  ```
49
51
  hexastack_cli/
50
52
  ├── domain/ # CliContext, OutputFormat enum
51
- ├── adapters/ # Rich presenters, Typer command runners
53
+ ├── adapters/ # Rich presenters, Typer command runners, TyperSuggest
54
+ ├── testing/ # CliNarrator, TerminalEvent (demo video & VTT recorder)
52
55
  └── infra/ # create_cli_app, CliBootstrapper (order=40), @cli_command, @cli_query, @cli_group, @feature_flag_command
53
56
  ```
54
57
 
@@ -56,7 +59,7 @@ hexastack_cli/
56
59
 
57
60
  | Category | Exports |
58
61
  |---|---|
59
- | **Application Factory** | `create_cli_app`, `CliBootstrapper` (order=30) |
62
+ | **Application Factory & Typo Tolerance** | `create_cli_app`, `TyperSuggest`, `SuggestGroup`, `SuggestCommand`, `CliBootstrapper` (order=40) |
60
63
  | **Decorators** | `@cli_command`, `@cli_query`, `@cli_group`, `@feature_flag_command` |
61
64
  | **Presenters** | `RichTerminalPresenter`, `ConsolePresenter`, `TablePresenter`, `JsonPresenter` |
62
65
  | **Testing & Demo Narration** | `CliNarrator`, `TerminalEvent` |
@@ -148,3 +151,57 @@ cli_query("status", aliases=["st", "health"], help="Check status of a service")(
148
151
  runtime = bootstrap(packages_to_scan=[__name__])
149
152
  cli_app = runtime.get("cli_app")
150
153
  ```
154
+
155
+ ---
156
+
157
+ ## 6. Standalone Typo-Tolerant CLI (`TyperSuggest`)
158
+
159
+ `TyperSuggest` is a drop-in replacement for `typer.Typer`. It intercepts mistyped commands and options, presenting suggestions and interactive confirmations without throwing cryptic syntax errors:
160
+
161
+ ```python
162
+ from hexastack_cli.adapters import TyperSuggest
163
+
164
+ app = TyperSuggest(help="My Resilient Service CLI")
165
+
166
+
167
+ @app.command()
168
+ def deploy(environment: str = "staging", force: bool = False):
169
+ print(f"Deploying to {environment} (force={force})")
170
+
171
+
172
+ if __name__ == "__main__":
173
+ app()
174
+ ```
175
+
176
+ ```bash
177
+ $ python cli.py deply
178
+ Unrecognized command 'deply'. Did you mean 'deploy'? [y/N]: y
179
+ Deploying to staging (force=False)
180
+
181
+ $ python cli.py deploy --frc
182
+ Unrecognized option '--frc'. Did you mean '--force'? [y/N]: y
183
+ Deploying to staging (force=True)
184
+ ```
185
+
186
+ In automated CI environments or redirected streams (`not sys.stdin.isatty()`), `TyperSuggest` prints the suggested correction to `stderr` and exits cleanly with error code `2` without hanging.
187
+
188
+ ---
189
+
190
+ ## 7. Automated Demo Recording & Video Slicing (`CliNarrator`)
191
+
192
+ ```python
193
+ from hexastack_cli.testing import CliNarrator
194
+
195
+ narrator = CliNarrator(record_video=True)
196
+ narrator.say("Scaffolding microservice...")
197
+ narrator.run("hexastack new web-api billing-service")
198
+
199
+ # Flush Chapter 1 video & VTT segment
200
+ narrator.checkpoint_segment("ch01-scaffolding")
201
+
202
+ narrator.say("Applying SQLite database migrations...")
203
+ narrator.run("hexastack db migrate")
204
+
205
+ # Flush Chapter 2 video & VTT segment
206
+ narrator.checkpoint_segment("ch02-migrations")
207
+ ```
@@ -20,9 +20,11 @@
20
20
 
21
21
  - **Nested Command Hierarchies**: Nest subcommands naturally (`app user create`, `app db migrate`) using `@cli_group`.
22
22
  - **Command Aliases**: Register multiple aliases for the same action (`app user new == app user create`).
23
+ - **Typo Tolerance & Suggestions (`TyperSuggest`)**: Drop-in replacement for `typer.Typer` that intercepts unrecognized subcommands or flags, computes closest matches via Levenshtein distance, prompts interactively for confirmation, and exits cleanly in CI/non-interactive pipelines.
23
24
  - **Feature Flag Gating**: Gate CLI commands dynamically with `@feature_flag_command(...)` and `@cli_command(..., feature_flag=...)`.
24
25
  - **Rich Formatted & CI-Friendly Output**: Beautiful tables, panels, and spinners for interactive terminals; clean text/JSON streaming for CI/CD pipelines.
25
26
  - **Direct CQRS Dispatching**: Declaratively expose domain commands (`@cli_command`) and queries (`@cli_query`) with automatic parameter parsing and validation.
27
+ - **Automated Demo Narration & Slicing (`CliNarrator`)**: Headless terminal recording generating asciinema streams, high-resolution `.webm` videos, chapterized `.checkpoint_segment()` flushes, and synchronized `.vtt` subtitles.
26
28
 
27
29
  ---
28
30
 
@@ -31,7 +33,8 @@
31
33
  ```
32
34
  hexastack_cli/
33
35
  ├── domain/ # CliContext, OutputFormat enum
34
- ├── adapters/ # Rich presenters, Typer command runners
36
+ ├── adapters/ # Rich presenters, Typer command runners, TyperSuggest
37
+ ├── testing/ # CliNarrator, TerminalEvent (demo video & VTT recorder)
35
38
  └── infra/ # create_cli_app, CliBootstrapper (order=40), @cli_command, @cli_query, @cli_group, @feature_flag_command
36
39
  ```
37
40
 
@@ -39,7 +42,7 @@ hexastack_cli/
39
42
 
40
43
  | Category | Exports |
41
44
  |---|---|
42
- | **Application Factory** | `create_cli_app`, `CliBootstrapper` (order=30) |
45
+ | **Application Factory & Typo Tolerance** | `create_cli_app`, `TyperSuggest`, `SuggestGroup`, `SuggestCommand`, `CliBootstrapper` (order=40) |
43
46
  | **Decorators** | `@cli_command`, `@cli_query`, `@cli_group`, `@feature_flag_command` |
44
47
  | **Presenters** | `RichTerminalPresenter`, `ConsolePresenter`, `TablePresenter`, `JsonPresenter` |
45
48
  | **Testing & Demo Narration** | `CliNarrator`, `TerminalEvent` |
@@ -131,3 +134,57 @@ cli_query("status", aliases=["st", "health"], help="Check status of a service")(
131
134
  runtime = bootstrap(packages_to_scan=[__name__])
132
135
  cli_app = runtime.get("cli_app")
133
136
  ```
137
+
138
+ ---
139
+
140
+ ## 6. Standalone Typo-Tolerant CLI (`TyperSuggest`)
141
+
142
+ `TyperSuggest` is a drop-in replacement for `typer.Typer`. It intercepts mistyped commands and options, presenting suggestions and interactive confirmations without throwing cryptic syntax errors:
143
+
144
+ ```python
145
+ from hexastack_cli.adapters import TyperSuggest
146
+
147
+ app = TyperSuggest(help="My Resilient Service CLI")
148
+
149
+
150
+ @app.command()
151
+ def deploy(environment: str = "staging", force: bool = False):
152
+ print(f"Deploying to {environment} (force={force})")
153
+
154
+
155
+ if __name__ == "__main__":
156
+ app()
157
+ ```
158
+
159
+ ```bash
160
+ $ python cli.py deply
161
+ Unrecognized command 'deply'. Did you mean 'deploy'? [y/N]: y
162
+ Deploying to staging (force=False)
163
+
164
+ $ python cli.py deploy --frc
165
+ Unrecognized option '--frc'. Did you mean '--force'? [y/N]: y
166
+ Deploying to staging (force=True)
167
+ ```
168
+
169
+ In automated CI environments or redirected streams (`not sys.stdin.isatty()`), `TyperSuggest` prints the suggested correction to `stderr` and exits cleanly with error code `2` without hanging.
170
+
171
+ ---
172
+
173
+ ## 7. Automated Demo Recording & Video Slicing (`CliNarrator`)
174
+
175
+ ```python
176
+ from hexastack_cli.testing import CliNarrator
177
+
178
+ narrator = CliNarrator(record_video=True)
179
+ narrator.say("Scaffolding microservice...")
180
+ narrator.run("hexastack new web-api billing-service")
181
+
182
+ # Flush Chapter 1 video & VTT segment
183
+ narrator.checkpoint_segment("ch01-scaffolding")
184
+
185
+ narrator.say("Applying SQLite database migrations...")
186
+ narrator.run("hexastack db migrate")
187
+
188
+ # Flush Chapter 2 video & VTT segment
189
+ narrator.checkpoint_segment("ch02-migrations")
190
+ ```
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hexastack-cli"
3
- version = "0.8.0"
3
+ version = "0.10.0"
4
4
  description = "Hexastack CLI presentation adapter with Typer and Rich"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -24,7 +24,7 @@ testing = ["playwright>=1.49.0"]
24
24
  cli = "hexastack_cli.infra.bootstrap:CliBootstrapper"
25
25
 
26
26
  [build-system]
27
- requires = ["uv_build>=0.12.3,<0.13.0"]
27
+ requires = ["uv_build>=0.12.3,<0.14.0"]
28
28
  build-backend = "uv_build"
29
29
 
30
30
  [tool.uv.sources.hexastack-core]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hexastack-cli"
3
- version = "0.8.0"
3
+ version = "0.10.0"
4
4
  description = "Hexastack CLI presentation adapter with Typer and Rich"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -25,7 +25,7 @@ testing = [
25
25
  cli = "hexastack_cli.infra.bootstrap:CliBootstrapper"
26
26
 
27
27
  [build-system]
28
- requires = ["uv_build>=0.12.3,<0.13.0"]
28
+ requires = ["uv_build>=0.12.3,<0.14.0"]
29
29
  build-backend = "uv_build"
30
30
 
31
31
  [tool.uv.sources]
@@ -0,0 +1,25 @@
1
+ from hexastack_cli.adapters.presenter import RichTerminalPresenter
2
+ from hexastack_cli.adapters.routing import (
3
+ register_cqrs_command,
4
+ register_cqrs_query,
5
+ )
6
+ from hexastack_cli.adapters.suggest import (
7
+ SuggestCommand,
8
+ SuggestGroup,
9
+ SuggestOptionParser,
10
+ TyperSuggest,
11
+ find_closest_match,
12
+ is_interactive,
13
+ )
14
+
15
+ __all__ = [
16
+ "find_closest_match",
17
+ "is_interactive",
18
+ "register_cqrs_command",
19
+ "register_cqrs_query",
20
+ "RichTerminalPresenter",
21
+ "SuggestCommand",
22
+ "SuggestGroup",
23
+ "SuggestOptionParser",
24
+ "TyperSuggest",
25
+ ]
@@ -307,6 +307,7 @@ def register_cqrs_command(
307
307
  presenter: RichTerminalPresenter | None = None,
308
308
  console: Console | None = None,
309
309
  feature_flag: str | None = None,
310
+ hidden: bool = False,
310
311
  ) -> None:
311
312
  """Register a CQRS Command model as a typed CLI sub-command on a Typer application.
312
313
 
@@ -325,6 +326,7 @@ def register_cqrs_command(
325
326
  presenter: Optional RichTerminalPresenter instance.
326
327
  console: Optional rich Console instance.
327
328
  feature_flag: Optional feature flag key required for execution.
329
+ hidden: Whether to hide the command from CLI help documentation.
328
330
 
329
331
  Returns:
330
332
  None.
@@ -343,7 +345,7 @@ def register_cqrs_command(
343
345
  console=console,
344
346
  feature_flag=feature_flag,
345
347
  )
346
- app.command(name=cmd_name, help=doc)(runner)
348
+ app.command(name=cmd_name, help=doc, hidden=hidden)(runner)
347
349
 
348
350
 
349
351
  def register_cqrs_query(
@@ -357,6 +359,7 @@ def register_cqrs_query(
357
359
  presenter: RichTerminalPresenter | None = None,
358
360
  console: Console | None = None,
359
361
  feature_flag: str | None = None,
362
+ hidden: bool = False,
360
363
  ) -> None:
361
364
  """Register a CQRS Query model as a typed CLI sub-command on a Typer application.
362
365
 
@@ -375,6 +378,7 @@ def register_cqrs_query(
375
378
  presenter: Optional RichTerminalPresenter instance.
376
379
  console: Optional rich Console instance.
377
380
  feature_flag: Optional feature flag key required for execution.
381
+ hidden: Whether to hide the command from CLI help documentation.
378
382
 
379
383
  Returns:
380
384
  None.
@@ -393,4 +397,4 @@ def register_cqrs_query(
393
397
  console=console,
394
398
  feature_flag=feature_flag,
395
399
  )
396
- app.command(name=qry_name, help=doc)(runner)
400
+ app.command(name=qry_name, help=doc, hidden=hidden)(runner)