deepctl-core 0.2.5__tar.gz → 0.2.7__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 (22) hide show
  1. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/PKG-INFO +1 -1
  2. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/pyproject.toml +1 -1
  3. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core/plugin_manager.py +16 -9
  4. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core/skill_generator.py +69 -17
  5. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core.egg-info/PKG-INFO +1 -1
  6. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/README.md +0 -0
  7. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/setup.cfg +0 -0
  8. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core/__init__.py +0 -0
  9. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core/auth.py +0 -0
  10. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core/base_command.py +0 -0
  11. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core/base_group_command.py +0 -0
  12. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core/client.py +0 -0
  13. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core/config.py +0 -0
  14. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core/models.py +0 -0
  15. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core/output.py +0 -0
  16. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core/plugin_env.py +0 -0
  17. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core/py.typed +0 -0
  18. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core/timing.py +0 -0
  19. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core.egg-info/SOURCES.txt +0 -0
  20. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core.egg-info/dependency_links.txt +0 -0
  21. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core.egg-info/requires.txt +0 -0
  22. {deepctl_core-0.2.5 → deepctl_core-0.2.7}/src/deepctl_core.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepctl-core
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: Core components for deepctl
5
5
  Author-email: Deepgram <devrel@deepgram.com>
6
6
  Maintainer-email: Deepgram <devrel@deepgram.com>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "deepctl-core"
7
- version = "0.2.5" # x-release-please-version
7
+ version = "0.2.7" # x-release-please-version
8
8
  description = "Core components for deepctl"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -422,15 +422,22 @@ class PluginManager:
422
422
  for arg in reversed(arguments):
423
423
  if arg.get("is_option", False):
424
424
  # Add as option
425
- cmd = click.option(
426
- *arg.get("names", []),
427
- default=arg.get("default"),
428
- help=arg.get("help", ""),
429
- type=arg.get("type", str),
430
- required=arg.get("required", False),
431
- is_flag=arg.get("is_flag", False),
432
- multiple=arg.get("multiple", False),
433
- )(cmd)
425
+ is_flag = arg.get("is_flag", False)
426
+ # Flags default to False (not None) so Click passes the
427
+ # right type. Also skip `type` for flags — Click manages
428
+ # its own bool type for flags; passing type=str converts
429
+ # the False default to the string "False" which is truthy.
430
+ default_fallback = False if is_flag else None
431
+ option_kwargs: dict[str, Any] = {
432
+ "default": arg.get("default", default_fallback),
433
+ "help": arg.get("help", ""),
434
+ "required": arg.get("required", False),
435
+ "is_flag": is_flag,
436
+ "multiple": arg.get("multiple", False),
437
+ }
438
+ if not is_flag:
439
+ option_kwargs["type"] = arg.get("type", str)
440
+ cmd = click.option(*arg.get("names", []), **option_kwargs)(cmd)
434
441
  else:
435
442
  # Add as argument
436
443
  cmd = click.argument(
@@ -84,7 +84,7 @@ def fetch_repo_skills(force: bool = False) -> dict[str, str]:
84
84
  pass
85
85
 
86
86
  base = f"https://raw.githubusercontent.com/{_SKILLS_REPO}/{_SKILLS_BRANCH}"
87
- skill_names = ["api", "docs", "starters", "mcp"]
87
+ skill_names = ["api", "docs", "setup-mcp", "starters"]
88
88
  skills: dict[str, str] = {}
89
89
 
90
90
  _REPO_CACHE_DIR.mkdir(parents=True, exist_ok=True)
@@ -659,24 +659,24 @@ class SkillGenerator(ABC):
659
659
  Mapping of file path -> content string
660
660
  """
661
661
 
662
- def install(self, commands: list[CommandMetadata], version: str) -> list[Path]:
663
- """Generate and write skill files with latest repo skills."""
664
- # Always fetch fresh skills from deepgram/skills repo
662
+ def install(
663
+ self,
664
+ commands: list[CommandMetadata], # noqa: ARG002
665
+ version: str, # noqa: ARG002
666
+ ) -> list[Path]:
667
+ """Fetch skills from deepgram/skills repo and install them."""
665
668
  repo_skills = fetch_repo_skills(force=True)
669
+ if not repo_skills:
670
+ return []
671
+ return self._write_repo_skills(repo_skills)
666
672
 
667
- files = self.generate(commands, version)
673
+ def _write_repo_skills(self, repo_skills: dict[str, str]) -> list[Path]:
674
+ """Write combined repo skill content to this tool's skill paths."""
675
+ combined = "\n\n---\n\n".join(repo_skills.values())
668
676
  written: list[Path] = []
669
- for path, content in files.items():
670
- # Append repo skill content to the generated file
671
- if repo_skills:
672
- sections = [
673
- f"\n\n## {name.title()}\n\n{body}"
674
- for name, body in repo_skills.items()
675
- ]
676
- content += "\n".join(sections)
677
-
677
+ for path in self.get_skill_paths():
678
678
  path.parent.mkdir(parents=True, exist_ok=True)
679
- path.write_text(content)
679
+ path.write_text(combined)
680
680
  written.append(path)
681
681
  return written
682
682
 
@@ -705,6 +705,10 @@ class ClaudeCodeGenerator(SkillGenerator):
705
705
  cli_name = "claude"
706
706
  display_name = "Claude Code"
707
707
 
708
+ @property
709
+ def _skill_dir(self) -> Path:
710
+ return Path.home() / ".claude" / "commands" / "deepgram"
711
+
708
712
  def detect(self) -> bool:
709
713
  return (
710
714
  Path.home().joinpath(".claude").is_dir()
@@ -712,13 +716,37 @@ class ClaudeCodeGenerator(SkillGenerator):
712
716
  )
713
717
 
714
718
  def get_skill_paths(self) -> list[Path]:
715
- return [Path.home() / ".claude" / "commands" / "deepctl.md"]
719
+ return [
720
+ self._skill_dir / f"{name}.md"
721
+ for name in ["api", "docs", "setup-mcp", "starters"]
722
+ ]
716
723
 
717
724
  def generate(
718
725
  self, commands: list[CommandMetadata], version: str
719
726
  ) -> dict[Path, str]:
720
727
  content = render_skill_content(commands, version, include_frontmatter=True)
721
- return {self.get_skill_paths()[0]: content}
728
+ return {self._skill_dir / "deepgram.md": content}
729
+
730
+ def _write_repo_skills(self, repo_skills: dict[str, str]) -> list[Path]:
731
+ self._skill_dir.mkdir(parents=True, exist_ok=True)
732
+ written: list[Path] = []
733
+ for name, content in repo_skills.items():
734
+ path = self._skill_dir / f"{name}.md"
735
+ path.write_text(content)
736
+ written.append(path)
737
+ return written
738
+
739
+ def remove(self) -> list[Path]:
740
+ removed: list[Path] = []
741
+ if self._skill_dir.exists():
742
+ for f in self._skill_dir.glob("*.md"):
743
+ f.unlink()
744
+ removed.append(f)
745
+ try:
746
+ self._skill_dir.rmdir()
747
+ except OSError:
748
+ pass
749
+ return removed
722
750
 
723
751
 
724
752
  class CodexGenerator(SkillGenerator):
@@ -758,6 +786,14 @@ class CodexGenerator(SkillGenerator):
758
786
  return before + section + after.lstrip("\n")
759
787
  return existing.rstrip("\n") + "\n\n" + section
760
788
 
789
+ def _write_repo_skills(self, repo_skills: dict[str, str]) -> list[Path]:
790
+ combined = "\n\n---\n\n".join(repo_skills.values())
791
+ wrapped = f"{self._BEGIN}\n{combined}\n{self._END}\n"
792
+ path = self.get_skill_paths()[0]
793
+ path.parent.mkdir(parents=True, exist_ok=True)
794
+ path.write_text(self._merge(path, wrapped))
795
+ return [path]
796
+
761
797
  def remove(self) -> list[Path]:
762
798
  path = self.get_skill_paths()[0]
763
799
  if not path.exists():
@@ -813,6 +849,14 @@ class GeminiGenerator(SkillGenerator):
813
849
  return before + section + after.lstrip("\n")
814
850
  return existing.rstrip("\n") + "\n\n" + section
815
851
 
852
+ def _write_repo_skills(self, repo_skills: dict[str, str]) -> list[Path]:
853
+ combined = "\n\n---\n\n".join(repo_skills.values())
854
+ wrapped = f"{self._BEGIN}\n{combined}\n{self._END}\n"
855
+ path = self.get_skill_paths()[0]
856
+ path.parent.mkdir(parents=True, exist_ok=True)
857
+ path.write_text(self._merge(path, wrapped))
858
+ return [path]
859
+
816
860
  def remove(self) -> list[Path]:
817
861
  path = self.get_skill_paths()[0]
818
862
  if not path.exists():
@@ -954,6 +998,14 @@ class OpenCodeGenerator(SkillGenerator):
954
998
  return before + section + after.lstrip("\n")
955
999
  return existing.rstrip("\n") + "\n\n" + section
956
1000
 
1001
+ def _write_repo_skills(self, repo_skills: dict[str, str]) -> list[Path]:
1002
+ combined = "\n\n---\n\n".join(repo_skills.values())
1003
+ wrapped = f"{self._BEGIN}\n{combined}\n{self._END}\n"
1004
+ path = self.get_skill_paths()[0]
1005
+ path.parent.mkdir(parents=True, exist_ok=True)
1006
+ path.write_text(self._merge(path, wrapped))
1007
+ return [path]
1008
+
957
1009
  def remove(self) -> list[Path]:
958
1010
  path = self.get_skill_paths()[0]
959
1011
  if not path.exists():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepctl-core
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: Core components for deepctl
5
5
  Author-email: Deepgram <devrel@deepgram.com>
6
6
  Maintainer-email: Deepgram <devrel@deepgram.com>
File without changes
File without changes