logion-cli 0.1.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 (135) hide show
  1. cli/__init__.py +2 -0
  2. cli/_config.py +51 -0
  3. cli/_confirm.py +16 -0
  4. cli/_context.py +17 -0
  5. cli/_course_bundle.py +46 -0
  6. cli/_course_capabilities.py +580 -0
  7. cli/_credentials.py +104 -0
  8. cli/_errors.py +82 -0
  9. cli/_first_run.py +90 -0
  10. cli/_harness/__init__.py +68 -0
  11. cli/_harness/base.py +106 -0
  12. cli/_harness/claude_code.py +168 -0
  13. cli/_harness/codex.py +79 -0
  14. cli/_harness/custom.py +55 -0
  15. cli/_harness/hermes.py +93 -0
  16. cli/_harness/opencode.py +255 -0
  17. cli/_local_state.py +1053 -0
  18. cli/_options.py +36 -0
  19. cli/_output.py +47 -0
  20. cli/_parser.py +73 -0
  21. cli/_recall_calibration.py +90 -0
  22. cli/_recall_ranker.py +74 -0
  23. cli/_taxonomy.py +120 -0
  24. cli/_update_policy.py +152 -0
  25. cli/_utils.py +16 -0
  26. cli/_version.py +26 -0
  27. cli/commands/__init__.py +2 -0
  28. cli/commands/admin.py +535 -0
  29. cli/commands/bounties.py +490 -0
  30. cli/commands/course_reviews/__init__.py +6 -0
  31. cli/commands/course_reviews/_download_handler.py +104 -0
  32. cli/commands/course_reviews/_render.py +129 -0
  33. cli/commands/course_reviews/handlers.py +197 -0
  34. cli/commands/course_reviews/parser.py +93 -0
  35. cli/commands/courses/__init__.py +6 -0
  36. cli/commands/courses/_capability_render.py +183 -0
  37. cli/commands/courses/_cmd_help.py +18 -0
  38. cli/commands/courses/_purchase.py +76 -0
  39. cli/commands/courses/_review_helpers.py +93 -0
  40. cli/commands/courses/_taxonomy_data.py +173 -0
  41. cli/commands/courses/_upload_bundle_validation.py +28 -0
  42. cli/commands/courses/_uploads_push.py +243 -0
  43. cli/commands/courses/capabilities.py +250 -0
  44. cli/commands/courses/capability_frontmatter.py +150 -0
  45. cli/commands/courses/handlers.py +50 -0
  46. cli/commands/courses/mutations.py +217 -0
  47. cli/commands/courses/parser.py +66 -0
  48. cli/commands/courses/parser_capabilities.py +95 -0
  49. cli/commands/courses/parser_sections.py +239 -0
  50. cli/commands/courses/parser_uploads.py +84 -0
  51. cli/commands/courses/parser_utils.py +65 -0
  52. cli/commands/courses/publication.py +60 -0
  53. cli/commands/courses/report_usage.py +131 -0
  54. cli/commands/courses/reviews.py +237 -0
  55. cli/commands/courses/taxonomy_handler.py +61 -0
  56. cli/commands/courses/taxonomy_suggest.py +197 -0
  57. cli/commands/courses/uploads.py +142 -0
  58. cli/commands/courses/versions.py +65 -0
  59. cli/commands/credits/__init__.py +6 -0
  60. cli/commands/credits/_helpers.py +153 -0
  61. cli/commands/credits/handlers.py +218 -0
  62. cli/commands/credits/parser.py +115 -0
  63. cli/commands/docs/__init__.py +6 -0
  64. cli/commands/docs/handlers.py +137 -0
  65. cli/commands/docs/parser.py +27 -0
  66. cli/commands/health/__init__.py +6 -0
  67. cli/commands/health/handlers.py +26 -0
  68. cli/commands/health/parser.py +20 -0
  69. cli/commands/identity/__init__.py +6 -0
  70. cli/commands/identity/_autopost.py +97 -0
  71. cli/commands/identity/_closing_copy.py +89 -0
  72. cli/commands/identity/_companion.py +232 -0
  73. cli/commands/identity/_companion_source.py +135 -0
  74. cli/commands/identity/_harness_select.py +85 -0
  75. cli/commands/identity/_onboarding_helpers.py +168 -0
  76. cli/commands/identity/handlers.py +173 -0
  77. cli/commands/identity/onboarding.py +246 -0
  78. cli/commands/identity/parser.py +72 -0
  79. cli/commands/listings/__init__.py +6 -0
  80. cli/commands/listings/handlers.py +135 -0
  81. cli/commands/listings/parser.py +57 -0
  82. cli/commands/notifications/__init__.py +6 -0
  83. cli/commands/notifications/handlers.py +120 -0
  84. cli/commands/notifications/parser.py +49 -0
  85. cli/commands/payments/__init__.py +6 -0
  86. cli/commands/payments/_orders_helpers.py +114 -0
  87. cli/commands/payments/handlers.py +138 -0
  88. cli/commands/payments/parser.py +97 -0
  89. cli/commands/recall/__init__.py +7 -0
  90. cli/commands/recall/handlers.py +87 -0
  91. cli/commands/recall/parser.py +70 -0
  92. cli/commands/referrals/__init__.py +6 -0
  93. cli/commands/referrals/_helpers.py +63 -0
  94. cli/commands/referrals/handlers.py +100 -0
  95. cli/commands/referrals/parser.py +65 -0
  96. cli/commands/reports/__init__.py +6 -0
  97. cli/commands/reports/handlers.py +57 -0
  98. cli/commands/reports/parser.py +52 -0
  99. cli/commands/skills/__init__.py +7 -0
  100. cli/commands/skills/_agent_symlink.py +161 -0
  101. cli/commands/skills/_finalize.py +112 -0
  102. cli/commands/skills/_inspect_handler.py +218 -0
  103. cli/commands/skills/_install_helpers.py +186 -0
  104. cli/commands/skills/_query_handlers.py +83 -0
  105. cli/commands/skills/_search_handler.py +136 -0
  106. cli/commands/skills/_update_handler.py +110 -0
  107. cli/commands/skills/_verify_handler.py +109 -0
  108. cli/commands/skills/handlers.py +202 -0
  109. cli/commands/skills/parser.py +154 -0
  110. cli/commands/workspace.py +406 -0
  111. cli/docs/README.md +5 -0
  112. cli/docs/__init__.py +1 -0
  113. cli/docs/bounties-and-referrals.md +18 -0
  114. cli/docs/concepts.md +47 -0
  115. cli/docs/creating-courses.md +25 -0
  116. cli/docs/credits-and-purchases.md +30 -0
  117. cli/docs/credits-terms.md +23 -0
  118. cli/docs/getting-started.md +95 -0
  119. cli/docs/marketplace-loop.md +108 -0
  120. cli/docs/privacy.md +30 -0
  121. cli/docs/referral-terms.md +24 -0
  122. cli/docs/reviews.md +47 -0
  123. cli/docs/safety.md +28 -0
  124. cli/docs/terms.md +54 -0
  125. cli/main.py +84 -0
  126. cli/templates/__init__.py +2 -0
  127. cli/templates/course_capabilities.template.yaml +189 -0
  128. cli/templates/course_license_apache-2.0.template.txt +30 -0
  129. cli/templates/course_license_logion-standard-course-v1.template.txt +49 -0
  130. cli/templates/course_license_mit.template.txt +21 -0
  131. logion_cli-0.1.0.dist-info/METADATA +49 -0
  132. logion_cli-0.1.0.dist-info/RECORD +135 -0
  133. logion_cli-0.1.0.dist-info/WHEEL +4 -0
  134. logion_cli-0.1.0.dist-info/entry_points.txt +4 -0
  135. logion_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
cli/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+ # SPDX-License-Identifier: MIT
2
+ """Logion CLI package."""
cli/_config.py ADDED
@@ -0,0 +1,51 @@
1
+ # SPDX-License-Identifier: MIT
2
+ """CLI configuration — env-var resolution and defaults."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import os
7
+ from dataclasses import dataclass
8
+
9
+ DEFAULT_BASE_URL = "https://api.logion.sh"
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class CliConfig:
14
+ """Resolved CLI configuration."""
15
+
16
+ api_key: str | None
17
+ base_url: str
18
+ json_output: bool
19
+ timeout: float | None
20
+ max_retries: int | None
21
+
22
+
23
+ def is_truthy(value: str | None) -> bool:
24
+ """Return True if *value* looks like a truthy env-var string."""
25
+ return value is not None and value.lower() in {"1", "true", "yes", "on"}
26
+
27
+
28
+ def is_admin_enabled() -> bool:
29
+ """Return True if ``LOGION_ENABLE_ADMIN`` is set to a truthy value."""
30
+ return is_truthy(os.getenv("LOGION_ENABLE_ADMIN"))
31
+
32
+
33
+ def resolve_config_from_args(
34
+ args: object,
35
+ ) -> CliConfig:
36
+ """Build a CliConfig from parsed argparse args + env vars."""
37
+ api_key: str | None = getattr(args, "api_key", None)
38
+ if api_key is None:
39
+ api_key = os.getenv("LOGION_API_KEY")
40
+
41
+ base_url: str | None = getattr(args, "base_url", None)
42
+ if base_url is None:
43
+ base_url = os.getenv("LOGION_BASE_URL", DEFAULT_BASE_URL)
44
+
45
+ return CliConfig(
46
+ api_key=api_key,
47
+ base_url=base_url,
48
+ json_output=getattr(args, "json_output", False),
49
+ timeout=getattr(args, "timeout", None),
50
+ max_retries=getattr(args, "max_retries", None),
51
+ )
cli/_confirm.py ADDED
@@ -0,0 +1,16 @@
1
+ # SPDX-License-Identifier: MIT
2
+ """Confirmation helper — require --yes for destructive actions."""
3
+
4
+ from __future__ import annotations
5
+
6
+ from cli._errors import print_err
7
+
8
+
9
+ def require_yes(yes: bool, action: str) -> int | None:
10
+ """Return ``None`` if *yes* is True, otherwise print a refusal and
11
+ return exit code 2.
12
+ """
13
+ if yes:
14
+ return None
15
+ print_err(f"This is a destructive action. Re-run with --yes to {action}.")
16
+ return 2
cli/_context.py ADDED
@@ -0,0 +1,17 @@
1
+ # SPDX-License-Identifier: MIT
2
+ """CLI context — builds a LogionClient from CliConfig."""
3
+
4
+ from __future__ import annotations
5
+
6
+ from cli._config import CliConfig
7
+ from logion import LogionClient
8
+
9
+
10
+ def make_client(config: CliConfig) -> LogionClient:
11
+ """Create a LogionClient from resolved CLI configuration."""
12
+ return LogionClient(
13
+ api_key=config.api_key,
14
+ base_url=config.base_url,
15
+ timeout=config.timeout,
16
+ max_retries=config.max_retries,
17
+ )
cli/_course_bundle.py ADDED
@@ -0,0 +1,46 @@
1
+ # SPDX-License-Identifier: MIT
2
+ """Validation helpers for publishable course bundles."""
3
+
4
+ from __future__ import annotations
5
+
6
+ from pathlib import Path
7
+
8
+ REQUIRED_BUNDLE_FILES = ("SKILL.md", "LICENSE", "course/capabilities.yaml")
9
+ LOGION_STANDARD_COURSE_LICENSE_NAME = "Logion Standard Course License v1.0"
10
+
11
+
12
+ class CourseBundleError(ValueError):
13
+ """Raised when a bundle is missing publish-time metadata."""
14
+
15
+
16
+ def read_bundle_license_text(bundle_dir: Path) -> str:
17
+ """Return the stripped bundle LICENSE text."""
18
+ return (bundle_dir / "LICENSE").read_text(encoding="utf-8").strip()
19
+
20
+
21
+ def is_logion_standard_course_license(license_text: str) -> bool:
22
+ """Return whether *license_text* is the Logion paid-course license."""
23
+ return LOGION_STANDARD_COURSE_LICENSE_NAME in license_text
24
+
25
+
26
+ def validate_course_bundle(bundle_dir: Path, *, paid: bool = False) -> None:
27
+ """Require the bundle files Logion needs before publication/install."""
28
+ missing = [
29
+ name
30
+ for name in REQUIRED_BUNDLE_FILES
31
+ if not (bundle_dir / name).is_file()
32
+ ]
33
+ if missing:
34
+ missing_csv = ", ".join(missing)
35
+ raise CourseBundleError(
36
+ "bundle is missing required file(s): "
37
+ f"{missing_csv}. "
38
+ "Every publishable course bundle must ship its own LICENSE file."
39
+ )
40
+ license_text = read_bundle_license_text(bundle_dir)
41
+ if not license_text:
42
+ raise CourseBundleError("LICENSE exists but is empty")
43
+ if paid and not is_logion_standard_course_license(license_text):
44
+ raise CourseBundleError(
45
+ "paid courses must ship the Logion Standard Course License v1.0"
46
+ )