chattool 7.1.3__tar.gz → 7.1.4__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 (105) hide show
  1. {chattool-7.1.3/src/chattool.egg-info → chattool-7.1.4}/PKG-INFO +26 -3
  2. {chattool-7.1.3 → chattool-7.1.4}/README.md +22 -0
  3. {chattool-7.1.3 → chattool-7.1.4}/pyproject.toml +3 -2
  4. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/__init__.py +1 -1
  5. chattool-7.1.4/src/chattool/client/main.py +202 -0
  6. {chattool-7.1.3 → chattool-7.1.4/src/chattool.egg-info}/PKG-INFO +26 -3
  7. chattool-7.1.3/src/chattool/client/main.py +0 -104
  8. {chattool-7.1.3 → chattool-7.1.4}/LICENSE +0 -0
  9. {chattool-7.1.3 → chattool-7.1.4}/MANIFEST.in +0 -0
  10. {chattool-7.1.3 → chattool-7.1.4}/scripts/migrate_chattool_envs_to_chatarch.py +0 -0
  11. {chattool-7.1.3 → chattool-7.1.4}/setup.cfg +0 -0
  12. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/_all.py +0 -0
  13. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/client/__init__.py +0 -0
  14. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/client/cert_client.py +0 -0
  15. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/client/svg2gif_client.py +0 -0
  16. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/config/__init__.py +0 -0
  17. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/config/aliyun.py +0 -0
  18. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/config/azure.py +0 -0
  19. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/config/base.py +0 -0
  20. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/config/browser.py +0 -0
  21. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/config/crs.py +0 -0
  22. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/config/elements.py +0 -0
  23. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/config/openai.py +0 -0
  24. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/config/skills.py +0 -0
  25. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/config/tencent.py +0 -0
  26. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/config/tplink.py +0 -0
  27. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/const.py +0 -0
  28. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/docker/__init__.py +0 -0
  29. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/docker/cli.py +0 -0
  30. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/docker/elements.py +0 -0
  31. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/docker/main.py +0 -0
  32. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/explore/__init__.py +0 -0
  33. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/explore/arxiv/__init__.py +0 -0
  34. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/explore/arxiv/cli.py +0 -0
  35. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/explore/arxiv/client.py +0 -0
  36. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/explore/arxiv/daily.py +0 -0
  37. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/explore/arxiv/harvest.py +0 -0
  38. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/explore/arxiv/models.py +0 -0
  39. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/explore/arxiv/presets.py +0 -0
  40. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/explore/arxiv/query.py +0 -0
  41. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/explore/cli.py +0 -0
  42. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/explore/wordpress/__init__.py +0 -0
  43. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/explore/wordpress/client.py +0 -0
  44. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/explore/wordpress/models.py +0 -0
  45. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/interaction/__init__.py +0 -0
  46. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/interaction/command_schema.py +0 -0
  47. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/interaction/policy.py +0 -0
  48. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/interaction/warnings.py +0 -0
  49. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/llm/__init__.py +0 -0
  50. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/llm/chattype.py +0 -0
  51. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/llm/response.py +0 -0
  52. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/mcp/__init__.py +0 -0
  53. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/mcp/catalog.py +0 -0
  54. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/mcp/cli.py +0 -0
  55. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/mcp/server.py +0 -0
  56. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/serve/__init__.py +0 -0
  57. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/serve/capture.py +0 -0
  58. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/serve/cert_server.py +0 -0
  59. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/serve/cli.py +0 -0
  60. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/serve/local.py +0 -0
  61. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/serve/oauth.py +0 -0
  62. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/serve/svg2gif.py +0 -0
  63. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/skill/__init__.py +0 -0
  64. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/skill/cli.py +0 -0
  65. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/skill/interaction.py +0 -0
  66. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/skill/platforms.py +0 -0
  67. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/skill/validation.py +0 -0
  68. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/__init__.py +0 -0
  69. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/browser/__init__.py +0 -0
  70. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/browser/base.py +0 -0
  71. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/browser/cli.py +0 -0
  72. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/browser/playwright_impl.py +0 -0
  73. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/browser/selenium.py +0 -0
  74. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/browser/test_browser.py +0 -0
  75. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/browser/test_module.py +0 -0
  76. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/browser/test_remote.py +0 -0
  77. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/browser/xhs_qrcode.py +0 -0
  78. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/cc/__init__.py +0 -0
  79. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/cc/cli.py +0 -0
  80. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/cert/__init__.py +0 -0
  81. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/cert/cert_server.py +0 -0
  82. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/cert/email.py +0 -0
  83. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/crs/__init__.py +0 -0
  84. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/crs/api.py +0 -0
  85. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/crs/cli.py +0 -0
  86. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/crs/openai_oauth.py +0 -0
  87. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/interact.py +0 -0
  88. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/nginx/__init__.py +0 -0
  89. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/nginx/cli.py +0 -0
  90. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/nginx/templates.py +0 -0
  91. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/tplogin.py +0 -0
  92. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/tools/tplogin_cli.py +0 -0
  93. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/utils/__init__.py +0 -0
  94. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/utils/basic.py +0 -0
  95. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/utils/custom_logger.py +0 -0
  96. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/utils/fastobj.py +0 -0
  97. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/utils/httpclient.py +0 -0
  98. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/utils/pathing.py +0 -0
  99. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/utils/test_helpers.py +0 -0
  100. {chattool-7.1.3 → chattool-7.1.4}/src/chattool/utils/urltool.py +0 -0
  101. {chattool-7.1.3 → chattool-7.1.4}/src/chattool.egg-info/SOURCES.txt +0 -0
  102. {chattool-7.1.3 → chattool-7.1.4}/src/chattool.egg-info/dependency_links.txt +0 -0
  103. {chattool-7.1.3 → chattool-7.1.4}/src/chattool.egg-info/entry_points.txt +0 -0
  104. {chattool-7.1.3 → chattool-7.1.4}/src/chattool.egg-info/requires.txt +0 -0
  105. {chattool-7.1.3 → chattool-7.1.4}/src/chattool.egg-info/top_level.txt +0 -0
@@ -1,11 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chattool
3
- Version: 7.1.3
3
+ Version: 7.1.4
4
4
  Summary: Toolkit for Chat API
5
5
  Author-email: Rex Wang <1073853456@qq.com>
6
6
  License: MIT license
7
- Project-URL: Homepage, https://github.com/cubenlp/chattool
8
- Project-URL: Repository, https://github.com/cubenlp/chattool
7
+ Project-URL: Homepage, https://github.com/CubeNLP/ChatTool
8
+ Project-URL: Repository, https://github.com/CubeNLP/ChatTool
9
+ Project-URL: Documentation, https://chattool.wzhecnu.cn
9
10
  Keywords: chattool
10
11
  Classifier: Development Status :: 2 - Pre-Alpha
11
12
  Classifier: Intended Audience :: Developers
@@ -316,6 +317,28 @@ chatpypi probe mychat
316
317
 
317
318
  如只想生成代码与测试骨架,可以用 `--without-mkdocs` 跳过 mkdocs/docs,用 `--without-workflows` 跳过 `.github/workflows/`。
318
319
 
320
+ ## CLI 树
321
+
322
+ `chattool --tree` 从真实 Click/LazyGroup 注册面生成,用于锁定当前 parent command surface。
323
+
324
+ ```text
325
+ chattool # Unified entry point for ChatTool services and scripts.
326
+ ├── --help # Show help for the current command.
327
+ ├── --version # Show package version.
328
+ ├── --tree # Print the registered CLI tree.
329
+ ├── browser # Browser automation helpers.
330
+ ├── cc # cc-connect helper commands.
331
+ ├── client # Remote client tools.
332
+ ├── crs # Claude Relay Service helper commands.
333
+ ├── docker # Docker utility commands.
334
+ ├── explore # Research and data exploration helpers.
335
+ ├── mcp # MCP server inspection and launch helpers.
336
+ ├── nginx # Nginx configuration generation helpers.
337
+ ├── serve # Local service helpers.
338
+ ├── skill # Install and manage ChatTool skills.
339
+ └── tplogin # TP-Link router helpers.
340
+ ```
341
+
319
342
  ## 开源协议
320
343
 
321
344
  MIT License
@@ -222,6 +222,28 @@ chatpypi probe mychat
222
222
 
223
223
  如只想生成代码与测试骨架,可以用 `--without-mkdocs` 跳过 mkdocs/docs,用 `--without-workflows` 跳过 `.github/workflows/`。
224
224
 
225
+ ## CLI 树
226
+
227
+ `chattool --tree` 从真实 Click/LazyGroup 注册面生成,用于锁定当前 parent command surface。
228
+
229
+ ```text
230
+ chattool # Unified entry point for ChatTool services and scripts.
231
+ ├── --help # Show help for the current command.
232
+ ├── --version # Show package version.
233
+ ├── --tree # Print the registered CLI tree.
234
+ ├── browser # Browser automation helpers.
235
+ ├── cc # cc-connect helper commands.
236
+ ├── client # Remote client tools.
237
+ ├── crs # Claude Relay Service helper commands.
238
+ ├── docker # Docker utility commands.
239
+ ├── explore # Research and data exploration helpers.
240
+ ├── mcp # MCP server inspection and launch helpers.
241
+ ├── nginx # Nginx configuration generation helpers.
242
+ ├── serve # Local service helpers.
243
+ ├── skill # Install and manage ChatTool skills.
244
+ └── tplogin # TP-Link router helpers.
245
+ ```
246
+
225
247
  ## 开源协议
226
248
 
227
249
  MIT License
@@ -118,8 +118,9 @@ dev = [
118
118
  "chattool[arch,docs,setup,tests,tools]",
119
119
  ]
120
120
  [project.urls]
121
- Homepage = "https://github.com/cubenlp/chattool"
122
- Repository = "https://github.com/cubenlp/chattool"
121
+ Homepage = "https://github.com/CubeNLP/ChatTool"
122
+ Repository = "https://github.com/CubeNLP/ChatTool"
123
+ Documentation = "https://chattool.wzhecnu.cn"
123
124
 
124
125
  [project.scripts]
125
126
  chattool = "chattool.client:main_cli"
@@ -4,7 +4,7 @@ import importlib
4
4
 
5
5
  __author__ = """Rex Wang"""
6
6
  __email__ = "1073853456@qq.com"
7
- __version__ = "7.1.3"
7
+ __version__ = "7.1.4"
8
8
 
9
9
  from dotenv import load_dotenv
10
10
 
@@ -0,0 +1,202 @@
1
+ from __future__ import annotations
2
+
3
+ import importlib
4
+ from typing import Callable
5
+
6
+ import click
7
+
8
+ from chattool import __version__
9
+
10
+
11
+ class LazyGroup(click.Group):
12
+ def __init__(
13
+ self,
14
+ *args,
15
+ lazy_commands: dict[str, Callable[[], click.Command]] | None = None,
16
+ lazy_command_help: dict[str, str] | None = None,
17
+ **kwargs,
18
+ ):
19
+ super().__init__(*args, **kwargs)
20
+ self._lazy_commands = dict(lazy_commands or {})
21
+ self._lazy_command_help = dict(lazy_command_help or {})
22
+
23
+ def list_commands(self, ctx: click.Context) -> list[str]:
24
+ commands = set(self.commands)
25
+ commands.update(self._lazy_commands)
26
+ return sorted(commands)
27
+
28
+ def get_command(self, ctx: click.Context, name: str) -> click.Command | None:
29
+ if name in self._lazy_commands:
30
+ self.commands[name] = self._lazy_commands.pop(name)()
31
+ return super().get_command(ctx, name)
32
+
33
+ def format_commands(
34
+ self, ctx: click.Context, formatter: click.HelpFormatter
35
+ ) -> None:
36
+ rows = []
37
+ for subcommand in self.list_commands(ctx):
38
+ if subcommand in self.commands:
39
+ cmd = self.commands[subcommand]
40
+ if cmd is None or cmd.hidden:
41
+ continue
42
+ help_text = cmd.get_short_help_str()
43
+ else:
44
+ help_text = self._lazy_command_help.get(subcommand, "")
45
+ rows.append((subcommand, help_text))
46
+
47
+ if rows:
48
+ with formatter.section("Commands"):
49
+ formatter.write_dl(rows)
50
+
51
+
52
+ _TREE_PARAM_PURPOSES = {
53
+ "help": "Show help for the current command.",
54
+ "version": "Show package version.",
55
+ "tree": "Print the registered CLI tree.",
56
+ }
57
+
58
+
59
+ def _load_attr(module_path: str, attr: str) -> click.Command:
60
+ module = importlib.import_module(module_path)
61
+ return getattr(module, attr)
62
+
63
+
64
+ def _build_serve_group() -> click.Command:
65
+ return _load_attr("chattool.serve.cli", "serve_cli")
66
+
67
+
68
+ def _build_client_group() -> click.Command:
69
+ return LazyGroup(
70
+ name="client",
71
+ help="Remote client tools.",
72
+ lazy_commands={
73
+ "cert": lambda: _load_attr("chattool.client.cert_client", "cert_client"),
74
+ "svg2gif": lambda: _load_attr(
75
+ "chattool.client.svg2gif_client", "svg2gif_client"
76
+ ),
77
+ },
78
+ lazy_command_help={
79
+ "cert": "Manage certificates through the remote cert service.",
80
+ "svg2gif": "Convert SVG to GIF through the remote svg2gif service.",
81
+ },
82
+ )
83
+
84
+
85
+ def _command_help(command: click.Command) -> str:
86
+ if command.help:
87
+ return command.help
88
+ if command.short_help:
89
+ return command.short_help
90
+ if command.callback and command.callback.__doc__:
91
+ return command.callback.__doc__.strip()
92
+ return ""
93
+
94
+
95
+ def _param_signature(param: click.Parameter) -> str:
96
+ opts = getattr(param, "opts", None) or []
97
+ secondary = getattr(param, "secondary_opts", None) or []
98
+ names = [*opts, *secondary]
99
+ if names:
100
+ return "/".join(names)
101
+ return param.human_readable_name.upper().replace("_", "-")
102
+
103
+
104
+ def _param_purpose(param: click.Parameter) -> str:
105
+ if param.name in _TREE_PARAM_PURPOSES:
106
+ return _TREE_PARAM_PURPOSES[param.name]
107
+ if isinstance(param, click.Option) and param.help:
108
+ return param.help.rstrip(".") + "."
109
+ return "Option registered by Click."
110
+
111
+
112
+ def _iter_command_rows(command: click.Command) -> list[tuple[str, str]]:
113
+ rows = [("--help", _TREE_PARAM_PURPOSES["help"])]
114
+ for param in command.params:
115
+ if getattr(param, "hidden", False):
116
+ continue
117
+ rows.append((_param_signature(param), _param_purpose(param)))
118
+ if isinstance(command, LazyGroup):
119
+ ctx = click.Context(command)
120
+ for name in command.list_commands(ctx):
121
+ if name in command.commands:
122
+ child = command.commands[name]
123
+ if child is None or child.hidden:
124
+ continue
125
+ help_text = command._lazy_command_help.get(name)
126
+ if help_text is None and name in command.commands:
127
+ help_text = command.commands[name].get_short_help_str()
128
+ rows.append((name, help_text or ""))
129
+ elif isinstance(command, click.Group):
130
+ for name, child in sorted(command.commands.items()):
131
+ if child is None or child.hidden:
132
+ continue
133
+ rows.append((name, child.get_short_help_str()))
134
+ return rows
135
+
136
+
137
+ def render_command_tree(command: click.Command, name: str = "chattool") -> str:
138
+ lines = [f"{name} # {_command_help(command)}"]
139
+ rows = _iter_command_rows(command)
140
+ for index, (label, purpose) in enumerate(rows):
141
+ connector = "└──" if index == len(rows) - 1 else "├──"
142
+ lines.append(f"{connector} {label} # {purpose}")
143
+ return "\n".join(lines)
144
+
145
+
146
+ @click.group(cls=LazyGroup, invoke_without_command=True)
147
+ @click.version_option(__version__, prog_name="chattool")
148
+ @click.option(
149
+ "--tree",
150
+ "show_tree",
151
+ is_flag=True,
152
+ help="Print the registered CLI tree.",
153
+ )
154
+ @click.pass_context
155
+ def cli(ctx: click.Context, show_tree: bool) -> None:
156
+ """Unified entry point for ChatTool services and scripts."""
157
+ if show_tree:
158
+ click.echo(render_command_tree(ctx.command, "chattool"))
159
+ ctx.exit(0)
160
+ if ctx.invoked_subcommand is None:
161
+ click.echo(ctx.get_help())
162
+ ctx.exit(0)
163
+
164
+
165
+ cli._lazy_commands.update(
166
+ {
167
+ "serve": _build_serve_group,
168
+ "client": _build_client_group,
169
+ "nginx": lambda: _load_attr("chattool.tools.nginx.cli", "cli"),
170
+ "mcp": lambda: _load_attr("chattool.mcp.cli", "cli"),
171
+ "tplogin": lambda: _load_attr("chattool.tools.tplogin_cli", "cli"),
172
+ "browser": lambda: _load_attr("chattool.tools.browser.cli", "cli"),
173
+ "skill": lambda: _load_attr("chattool.skill.cli", "skill_cli"),
174
+ "cc": lambda: _load_attr("chattool.tools.cc.cli", "cli"),
175
+ "docker": lambda: _load_attr("chattool.docker.cli", "docker_cmd"),
176
+ "explore": lambda: _load_attr("chattool.explore.cli", "explore_cli"),
177
+ "crs": lambda: _load_attr("chattool.tools.crs.cli", "cli"),
178
+ }
179
+ )
180
+ cli._lazy_command_help.update(
181
+ {
182
+ "browser": "Browser automation helpers.",
183
+ "cc": "cc-connect helper commands.",
184
+ "client": "Remote client tools.",
185
+ "crs": "Claude Relay Service helper commands.",
186
+ "docker": "Docker utility commands.",
187
+ "explore": "Research and data exploration helpers.",
188
+ "mcp": "MCP server inspection and launch helpers.",
189
+ "nginx": "Nginx configuration generation helpers.",
190
+ "serve": "Local service helpers.",
191
+ "skill": "Install and manage ChatTool skills.",
192
+ "tplogin": "TP-Link router helpers.",
193
+ }
194
+ )
195
+
196
+
197
+ def main():
198
+ cli()
199
+
200
+
201
+ if __name__ == "__main__":
202
+ main()
@@ -1,11 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chattool
3
- Version: 7.1.3
3
+ Version: 7.1.4
4
4
  Summary: Toolkit for Chat API
5
5
  Author-email: Rex Wang <1073853456@qq.com>
6
6
  License: MIT license
7
- Project-URL: Homepage, https://github.com/cubenlp/chattool
8
- Project-URL: Repository, https://github.com/cubenlp/chattool
7
+ Project-URL: Homepage, https://github.com/CubeNLP/ChatTool
8
+ Project-URL: Repository, https://github.com/CubeNLP/ChatTool
9
+ Project-URL: Documentation, https://chattool.wzhecnu.cn
9
10
  Keywords: chattool
10
11
  Classifier: Development Status :: 2 - Pre-Alpha
11
12
  Classifier: Intended Audience :: Developers
@@ -316,6 +317,28 @@ chatpypi probe mychat
316
317
 
317
318
  如只想生成代码与测试骨架,可以用 `--without-mkdocs` 跳过 mkdocs/docs,用 `--without-workflows` 跳过 `.github/workflows/`。
318
319
 
320
+ ## CLI 树
321
+
322
+ `chattool --tree` 从真实 Click/LazyGroup 注册面生成,用于锁定当前 parent command surface。
323
+
324
+ ```text
325
+ chattool # Unified entry point for ChatTool services and scripts.
326
+ ├── --help # Show help for the current command.
327
+ ├── --version # Show package version.
328
+ ├── --tree # Print the registered CLI tree.
329
+ ├── browser # Browser automation helpers.
330
+ ├── cc # cc-connect helper commands.
331
+ ├── client # Remote client tools.
332
+ ├── crs # Claude Relay Service helper commands.
333
+ ├── docker # Docker utility commands.
334
+ ├── explore # Research and data exploration helpers.
335
+ ├── mcp # MCP server inspection and launch helpers.
336
+ ├── nginx # Nginx configuration generation helpers.
337
+ ├── serve # Local service helpers.
338
+ ├── skill # Install and manage ChatTool skills.
339
+ └── tplogin # TP-Link router helpers.
340
+ ```
341
+
319
342
  ## 开源协议
320
343
 
321
344
  MIT License
@@ -1,104 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import importlib
4
- from typing import Callable
5
-
6
- import click
7
-
8
-
9
- class LazyGroup(click.Group):
10
- def __init__(
11
- self,
12
- *args,
13
- lazy_commands: dict[str, Callable[[], click.Command]] | None = None,
14
- lazy_command_help: dict[str, str] | None = None,
15
- **kwargs,
16
- ):
17
- super().__init__(*args, **kwargs)
18
- self._lazy_commands = dict(lazy_commands or {})
19
- self._lazy_command_help = dict(lazy_command_help or {})
20
-
21
- def list_commands(self, ctx: click.Context) -> list[str]:
22
- commands = set(self.commands)
23
- commands.update(self._lazy_commands)
24
- return sorted(commands)
25
-
26
- def get_command(self, ctx: click.Context, name: str) -> click.Command | None:
27
- if name in self._lazy_commands:
28
- self.commands[name] = self._lazy_commands.pop(name)()
29
- return super().get_command(ctx, name)
30
-
31
- def format_commands(
32
- self, ctx: click.Context, formatter: click.HelpFormatter
33
- ) -> None:
34
- rows = []
35
- for subcommand in self.list_commands(ctx):
36
- if subcommand in self.commands:
37
- cmd = self.commands[subcommand]
38
- if cmd is None or cmd.hidden:
39
- continue
40
- help_text = cmd.get_short_help_str()
41
- else:
42
- help_text = self._lazy_command_help.get(subcommand, "")
43
- rows.append((subcommand, help_text))
44
-
45
- if rows:
46
- with formatter.section("Commands"):
47
- formatter.write_dl(rows)
48
-
49
-
50
- def _load_attr(module_path: str, attr: str) -> click.Command:
51
- module = importlib.import_module(module_path)
52
- return getattr(module, attr)
53
-
54
-
55
- def _build_serve_group() -> click.Command:
56
- return _load_attr("chattool.serve.cli", "serve_cli")
57
-
58
-
59
- def _build_client_group() -> click.Command:
60
- return LazyGroup(
61
- name="client",
62
- help="Remote client tools.",
63
- lazy_commands={
64
- "cert": lambda: _load_attr("chattool.client.cert_client", "cert_client"),
65
- "svg2gif": lambda: _load_attr(
66
- "chattool.client.svg2gif_client", "svg2gif_client"
67
- ),
68
- },
69
- lazy_command_help={
70
- "cert": "Manage certificates through the remote cert service.",
71
- "svg2gif": "Convert SVG to GIF through the remote svg2gif service.",
72
- },
73
- )
74
-
75
-
76
- @click.group(cls=LazyGroup)
77
- def cli():
78
- """ChatTool CLI - Unified entry point for ChatTool services and scripts."""
79
- pass
80
-
81
-
82
- cli._lazy_commands.update(
83
- {
84
- "serve": _build_serve_group,
85
- "client": _build_client_group,
86
- "nginx": lambda: _load_attr("chattool.tools.nginx.cli", "cli"),
87
- "mcp": lambda: _load_attr("chattool.mcp.cli", "cli"),
88
- "tplogin": lambda: _load_attr("chattool.tools.tplogin_cli", "cli"),
89
- "browser": lambda: _load_attr("chattool.tools.browser.cli", "cli"),
90
- "skill": lambda: _load_attr("chattool.skill.cli", "skill_cli"),
91
- "cc": lambda: _load_attr("chattool.tools.cc.cli", "cli"),
92
- "docker": lambda: _load_attr("chattool.docker.cli", "docker_cmd"),
93
- "explore": lambda: _load_attr("chattool.explore.cli", "explore_cli"),
94
- "crs": lambda: _load_attr("chattool.tools.crs.cli", "cli"),
95
- }
96
- )
97
-
98
-
99
- def main():
100
- cli()
101
-
102
-
103
- if __name__ == "__main__":
104
- main()
File without changes
File without changes
File without changes
File without changes
File without changes