apcore-cli 0.3.0__tar.gz → 0.3.1__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 (69) hide show
  1. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/CHANGELOG.md +20 -0
  2. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/PKG-INFO +3 -3
  3. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/README.md +1 -1
  4. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/pyproject.toml +2 -2
  5. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/__main__.py +29 -3
  6. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/cli.py +1 -1
  7. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/init_cmd.py +5 -0
  8. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/shell.py +8 -2
  9. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/.github/CODEOWNERS +0 -0
  10. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/.github/copilot-ignore +0 -0
  11. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/.github/workflows/ci.yml +0 -0
  12. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/.gitignore +0 -0
  13. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/.gitmessage +0 -0
  14. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/.pre-commit-config.yaml +0 -0
  15. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/CLAUDE.md +0 -0
  16. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/commands/ops.py +0 -0
  17. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/examples/extensions/math/add.py +0 -0
  18. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/examples/extensions/math/multiply.py +0 -0
  19. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/examples/extensions/sysutil/disk.py +0 -0
  20. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/examples/extensions/sysutil/env.py +0 -0
  21. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/examples/extensions/sysutil/info.py +0 -0
  22. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/examples/extensions/text/reverse.py +0 -0
  23. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/examples/extensions/text/upper.py +0 -0
  24. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/examples/extensions/text/wordcount.py +0 -0
  25. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/examples/run_examples.sh +0 -0
  26. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/planning/approval-gate.md +0 -0
  27. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/planning/config-resolver.md +0 -0
  28. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/planning/core-dispatcher.md +0 -0
  29. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/planning/discovery.md +0 -0
  30. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/planning/grouped-commands.md +0 -0
  31. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/planning/output-formatter.md +0 -0
  32. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/planning/overview.md +0 -0
  33. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/planning/schema-parser.md +0 -0
  34. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/planning/security-manager.md +0 -0
  35. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/planning/shell-integration.md +0 -0
  36. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/planning/state.json +0 -0
  37. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/__init__.py +0 -0
  38. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/_sandbox_runner.py +0 -0
  39. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/approval.py +0 -0
  40. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/config.py +0 -0
  41. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/discovery.py +0 -0
  42. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/display_helpers.py +0 -0
  43. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/output.py +0 -0
  44. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/ref_resolver.py +0 -0
  45. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/schema_parser.py +0 -0
  46. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/security/__init__.py +0 -0
  47. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/security/audit.py +0 -0
  48. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/security/auth.py +0 -0
  49. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/security/config_encryptor.py +0 -0
  50. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/src/apcore_cli/security/sandbox.py +0 -0
  51. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/__init__.py +0 -0
  52. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/conftest.py +0 -0
  53. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_approval.py +0 -0
  54. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_bugfixes.py +0 -0
  55. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_cli.py +0 -0
  56. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_config.py +0 -0
  57. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_discovery.py +0 -0
  58. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_e2e.py +0 -0
  59. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_init_cmd.py +0 -0
  60. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_integration.py +0 -0
  61. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_output.py +0 -0
  62. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_ref_resolver.py +0 -0
  63. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_schema_parser.py +0 -0
  64. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_security/__init__.py +0 -0
  65. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_security/test_audit.py +0 -0
  66. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_security/test_auth.py +0 -0
  67. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_security/test_config_encryptor.py +0 -0
  68. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_security/test_sandbox.py +0 -0
  69. {apcore_cli-0.3.0 → apcore_cli-0.3.1}/tests/test_shell.py +0 -0
@@ -5,6 +5,26 @@ All notable changes to apcore-cli (Python SDK) will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.3.1] - 2026-03-27
9
+
10
+ ### Added
11
+
12
+ - **DisplayResolver integration** — `__main__.py` integrates `DisplayResolver` from `apcore-toolkit` (optional) when `--binding` option is provided; gracefully skipped when not installed.
13
+ - **`init` to `BUILTIN_COMMANDS`** — `init` subcommand is now registered in the builtin commands set.
14
+ - **`APCORE_AUTH_API_KEY` to man page** — environment variable documented in generated roff man page.
15
+ - **Grouped shell completion with `_APCORE_GRP`** — bash/zsh/fish completion scripts now support two-level group/command completion via the `_APCORE_GRP` environment variable (`shell.py`).
16
+ - **Path traversal validation for `--dir` in `init` command** — rejects paths containing `..` segments to prevent directory escape (`init_cmd.py`).
17
+
18
+ ### Fixed
19
+
20
+ - **`RegistryWriter` API call** — constructor now called without parameters; fixes `TypeError` introduced by upstream API change.
21
+
22
+ ### Changed
23
+
24
+ - `apcore` dependency bumped to `>=0.14.0`.
25
+
26
+ ---
27
+
8
28
  ## [0.3.0] - 2026-03-23
9
29
 
10
30
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apcore-cli
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Terminal adapter for apcore — execute AI-Perceivable modules from the command line
5
5
  Project-URL: Homepage, https://aiperceivable.com
6
6
  Project-URL: Repository, https://github.com/aiperceivable/apcore-cli-python
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.13
20
20
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
22
  Requires-Python: >=3.11
23
- Requires-Dist: apcore>=0.13.1
23
+ Requires-Dist: apcore>=0.14.0
24
24
  Requires-Dist: click>=8.1
25
25
  Requires-Dist: cryptography>=41.0
26
26
  Requires-Dist: jsonschema>=4.20
@@ -85,7 +85,7 @@ Terminal adapter for apcore. Execute AI-Perceivable modules from the command lin
85
85
  pip install apcore-cli
86
86
  ```
87
87
 
88
- Requires Python 3.11+ and `apcore >= 0.13.0`.
88
+ Requires Python 3.11+ and `apcore >= 0.14.0`.
89
89
 
90
90
  ## Quick Start
91
91
 
@@ -48,7 +48,7 @@ Terminal adapter for apcore. Execute AI-Perceivable modules from the command lin
48
48
  pip install apcore-cli
49
49
  ```
50
50
 
51
- Requires Python 3.11+ and `apcore >= 0.13.0`.
51
+ Requires Python 3.11+ and `apcore >= 0.14.0`.
52
52
 
53
53
  ## Quick Start
54
54
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "apcore-cli"
7
- version = "0.3.0"
7
+ version = "0.3.1"
8
8
  description = "Terminal adapter for apcore — execute AI-Perceivable modules from the command line"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -26,7 +26,7 @@ classifiers = [
26
26
  "Environment :: Console",
27
27
  ]
28
28
  dependencies = [
29
- "apcore>=0.13.1",
29
+ "apcore>=0.14.0",
30
30
  "click>=8.1",
31
31
  "jsonschema>=4.20",
32
32
  "rich>=13.0",
@@ -45,10 +45,16 @@ def _extract_commands_dir(argv: list[str] | None = None) -> str | None:
45
45
  return _extract_argv_option(argv, "--commands-dir")
46
46
 
47
47
 
48
+ def _extract_binding_path(argv: list[str] | None = None) -> str | None:
49
+ """Extract --binding value from argv before Click parses it."""
50
+ return _extract_argv_option(argv, "--binding")
51
+
52
+
48
53
  def create_cli(
49
54
  extensions_dir: str | None = None,
50
55
  prog_name: str | None = None,
51
56
  commands_dir: str | None = None,
57
+ binding_path: str | None = None,
52
58
  ) -> click.Group:
53
59
  """Create the CLI application.
54
60
 
@@ -62,6 +68,9 @@ def create_cli(
62
68
  commands_dir: Directory containing convention-based modules.
63
69
  When set, scans for plain-function modules and registers
64
70
  them via ConventionScanner (requires apcore-toolkit).
71
+ binding_path: Path to binding.yaml file or directory for display resolution.
72
+ When set, applies DisplayResolver to convention-scanned modules
73
+ (requires apcore-toolkit).
65
74
  """
66
75
  if prog_name is None:
67
76
  prog_name = os.path.basename(sys.argv[0]) or "apcore-cli"
@@ -138,8 +147,17 @@ def create_cli(
138
147
  conv_scanner = ConventionScanner()
139
148
  conv_modules = conv_scanner.scan(commands_dir)
140
149
  if conv_modules:
141
- writer = RegistryWriter(registry=registry)
142
- writer.write(conv_modules)
150
+ if binding_path is not None:
151
+ try:
152
+ from apcore_toolkit import DisplayResolver
153
+
154
+ display_resolver = DisplayResolver()
155
+ conv_modules = display_resolver.resolve(conv_modules, binding_path=binding_path)
156
+ logger.info("DisplayResolver: applied binding from %s", binding_path)
157
+ except ImportError:
158
+ logger.warning("DisplayResolver not available in apcore-toolkit")
159
+ writer = RegistryWriter()
160
+ writer.write(conv_modules, registry)
143
161
  logger.info("Convention scanner: registered %d modules from %s", len(conv_modules), commands_dir)
144
162
  except ImportError:
145
163
  logger.warning("apcore-toolkit not installed — convention module scanning unavailable")
@@ -182,6 +200,12 @@ def create_cli(
182
200
  default=None,
183
201
  help="Path to convention-based commands directory.",
184
202
  )
203
+ @click.option(
204
+ "--binding",
205
+ "binding_opt",
206
+ default=None,
207
+ help="Path to binding.yaml file or directory for display resolution.",
208
+ )
185
209
  @click.option(
186
210
  "--log-level",
187
211
  default=None,
@@ -193,6 +217,7 @@ def create_cli(
193
217
  ctx: click.Context,
194
218
  extensions_dir_opt: str | None = None,
195
219
  commands_dir_opt: str | None = None,
220
+ binding_opt: str | None = None,
196
221
  log_level: str | None = None,
197
222
  ) -> None:
198
223
  if log_level is not None:
@@ -228,7 +253,8 @@ def main(prog_name: str | None = None) -> None:
228
253
  """
229
254
  ext_dir = _extract_extensions_dir()
230
255
  cmd_dir = _extract_commands_dir()
231
- cli = create_cli(extensions_dir=ext_dir, prog_name=prog_name, commands_dir=cmd_dir)
256
+ bind_path = _extract_binding_path()
257
+ cli = create_cli(extensions_dir=ext_dir, prog_name=prog_name, commands_dir=cmd_dir, binding_path=bind_path)
232
258
  cli(standalone_mode=True)
233
259
 
234
260
 
@@ -27,7 +27,7 @@ if TYPE_CHECKING:
27
27
 
28
28
  logger = logging.getLogger("apcore_cli.cli")
29
29
 
30
- BUILTIN_COMMANDS = ["exec", "list", "describe", "completion", "man"]
30
+ BUILTIN_COMMANDS = ["completion", "describe", "exec", "init", "list", "man"]
31
31
 
32
32
  # Module-level audit logger, set during CLI init
33
33
  _audit_logger: AuditLogger | None = None
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import sys
5
6
  from pathlib import Path
6
7
 
7
8
  import click
@@ -59,6 +60,10 @@ def register_init_command(cli: click.Group) -> None:
59
60
 
60
61
  MODULE_ID is the module identifier (e.g., ops.deploy, user.create).
61
62
  """
63
+ if output_dir is not None and ".." in Path(output_dir).parts:
64
+ click.echo("Error: Output directory must not contain '..' path components.", err=True)
65
+ sys.exit(2)
66
+
62
67
  # Parse module_id into parts
63
68
  parts = module_id.rsplit(".", 1)
64
69
  if len(parts) == 2:
@@ -59,7 +59,7 @@ def _generate_bash_completion(prog_name: str) -> str:
59
59
  "\n"
60
60
  " if [[ ${COMP_CWORD} -eq 1 ]]; then\n"
61
61
  f" local all_ids=$({groups_and_top_cmd})\n"
62
- ' local builtins="exec list describe completion man"\n'
62
+ ' local builtins="completion describe exec init list man"\n'
63
63
  ' COMPREPLY=( $(compgen -W "${builtins} ${all_ids}" -- ${cur}) )\n'
64
64
  " return 0\n"
65
65
  " fi\n"
@@ -124,6 +124,7 @@ def _generate_zsh_completion(prog_name: str) -> str:
124
124
  " 'list:List available modules'\n"
125
125
  " 'describe:Show module metadata and schema'\n"
126
126
  " 'completion:Generate shell completion script'\n"
127
+ " 'init:Scaffolding commands'\n"
127
128
  " 'man:Generate man page'\n"
128
129
  " )\n"
129
130
  "\n"
@@ -208,6 +209,8 @@ def _generate_fish_completion(prog_name: str) -> str:
208
209
  f'complete -c {quoted} -n "__fish_use_subcommand"'
209
210
  ' -a completion -d "Generate shell completion script"\n'
210
211
  f'complete -c {quoted} -n "__fish_use_subcommand"'
212
+ ' -a init -d "Scaffolding commands"\n'
213
+ f'complete -c {quoted} -n "__fish_use_subcommand"'
211
214
  ' -a man -d "Generate man page"\n'
212
215
  f'complete -c {quoted} -n "__fish_use_subcommand"'
213
216
  f' -a "({groups_and_top_cmd})" -d "Module group or command"\n'
@@ -304,6 +307,9 @@ def _generate_man_page(command_name: str, command: click.Command | None, prog_na
304
307
  "Global apcore logging verbosity. One of: DEBUG, INFO, WARNING, ERROR. "
305
308
  "Used as fallback when \\fBAPCORE_CLI_LOGGING_LEVEL\\fR is not set. Default: WARNING."
306
309
  )
310
+ sections.append(".TP")
311
+ sections.append("\\fBAPCORE_AUTH_API_KEY\\fR")
312
+ sections.append("API key for authenticating with the apcore registry.")
307
313
 
308
314
  sections.append(".SH EXIT CODES")
309
315
  exit_codes = [
@@ -380,7 +386,7 @@ def register_shell_commands(cli: click.Group, prog_name: str = "apcore-cli") ->
380
386
  parent_group = parent.command
381
387
  cmd = parent_group.commands.get(command) if isinstance(parent_group, click.Group) else None
382
388
 
383
- known_builtins = {"list", "describe", "completion", "man"}
389
+ known_builtins = {"completion", "describe", "exec", "init", "list", "man"}
384
390
  if cmd is None and command not in known_builtins:
385
391
  click.echo(f"Error: Unknown command '{command}'.", err=True)
386
392
  sys.exit(2)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes