adam-community 0.0.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.
@@ -0,0 +1,53 @@
1
+ Metadata-Version: 2.2
2
+ Name: adam_community
3
+ Version: 0.0.4
4
+ Summary: Adam Community Tools and Utilities
5
+ Home-page: https://github.com/yourusername/adam-community
6
+ Author: Adam Community
7
+ Author-email: admin@sidereus-ai.com
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown
13
+ Requires-Dist: requests>=2.31.0
14
+ Requires-Dist: click>=8.0.0
15
+ Requires-Dist: docstring-parser>=0.15
16
+ Requires-Dist: rich>=13.0.0
17
+ Dynamic: author
18
+ Dynamic: author-email
19
+ Dynamic: classifier
20
+ Dynamic: description
21
+ Dynamic: description-content-type
22
+ Dynamic: home-page
23
+ Dynamic: requires-dist
24
+ Dynamic: requires-python
25
+ Dynamic: summary
26
+
27
+ # Adam Community
28
+
29
+ Adam Community 是一个 Python 工具包,提供了一系列实用工具和功能,用于与 Adam 社区相关的开发工作。
30
+
31
+ 安装依赖:
32
+ ```bash
33
+ make install
34
+ ```
35
+
36
+
37
+ ## 使用方法
38
+
39
+ 安装完成后,您可以在 Python 代码中导入并使用该包:
40
+
41
+ ```python
42
+ from adam_community import tool
43
+ from adam_community import util
44
+
45
+ # 使用相关功能
46
+ ```
47
+
48
+ ## 开发
49
+
50
+ 运行测试:
51
+ ```bash
52
+ make test
53
+ ```
@@ -0,0 +1,27 @@
1
+ # Adam Community
2
+
3
+ Adam Community 是一个 Python 工具包,提供了一系列实用工具和功能,用于与 Adam 社区相关的开发工作。
4
+
5
+ 安装依赖:
6
+ ```bash
7
+ make install
8
+ ```
9
+
10
+
11
+ ## 使用方法
12
+
13
+ 安装完成后,您可以在 Python 代码中导入并使用该包:
14
+
15
+ ```python
16
+ from adam_community import tool
17
+ from adam_community import util
18
+
19
+ # 使用相关功能
20
+ ```
21
+
22
+ ## 开发
23
+
24
+ 运行测试:
25
+ ```bash
26
+ make test
27
+ ```
@@ -0,0 +1,4 @@
1
+ from .util import messageSend, knowledgeSearch, completionCreate, runCmd
2
+ from .tool import Tool
3
+
4
+ __all__ = ['Tool', 'messageSend', 'knowledgeSearch', 'completionCreate', 'runCmd']
File without changes
@@ -0,0 +1,269 @@
1
+ import json
2
+ import zipfile
3
+ from pathlib import Path
4
+ from typing import Tuple, List
5
+ from rich.console import Console
6
+ from rich.panel import Panel
7
+ from rich.tree import Tree
8
+ from .parser import parse_directory
9
+
10
+ console = Console()
11
+
12
+ def check_python_files(directory: Path) -> Tuple[bool, List[str]]:
13
+ """检查所有 Python 文件是否都有参数定义"""
14
+ tree = Tree("📦 Python 文件检查")
15
+ errors = []
16
+ warnings = []
17
+ functions = parse_directory(directory)
18
+
19
+ tree.add(f"找到 {len(functions)} 个类定义")
20
+ for func in functions:
21
+ func_info = func["function"]
22
+
23
+ # 检查描述长度
24
+ description = func_info.get("description")
25
+ if description is None or not description:
26
+ warning_msg = f"⚠️ {func_info['file']}: {func_info['name']} 没有描述"
27
+ tree.add(warning_msg)
28
+ warnings.append(warning_msg)
29
+ elif len(description) > 1024:
30
+ error_msg = f"❌ {func_info['file']}: {func_info['name']} 描述长度超过1024字符 ({len(description)})"
31
+ tree.add(error_msg)
32
+ errors.append(error_msg)
33
+ else:
34
+ tree.add(f"✓ {func_info['file']}: {func_info['name']} 描述长度: {len(description)}")
35
+
36
+ # 检查参数定义
37
+ if not func_info["parameters"]["properties"]:
38
+ warning_msg = f"⚠️ {func_info['file']}: {func_info['name']} 没有参数定义"
39
+ tree.add(warning_msg)
40
+ warnings.append(warning_msg)
41
+ else:
42
+ # 检查参数类型是否都是有效的JSON Schema类型
43
+ param_errors = []
44
+ for param_name, param_info in func_info["parameters"]["properties"].items():
45
+ if "type" not in param_info:
46
+ param_errors.append(f"参数 '{param_name}' 缺少类型定义")
47
+ elif param_info["type"] not in ["string", "integer", "number", "boolean", "array", "object", "null"]:
48
+ param_errors.append(f"参数 '{param_name}' 类型 '{param_info['type']}' 不是有效的JSON Schema类型")
49
+
50
+ if param_errors:
51
+ for param_error in param_errors:
52
+ error_msg = f"❌ {func_info['file']}: {func_info['name']} - {param_error}"
53
+ tree.add(error_msg)
54
+ errors.append(error_msg)
55
+ else:
56
+ tree.add(f"✓ {func_info['file']}: {func_info['name']} 参数类型验证通过")
57
+
58
+ if errors:
59
+ tree.add("❌ 检查未通过")
60
+ else:
61
+ tree.add("✅ 检查通过")
62
+
63
+ # 显示警告信息
64
+ if warnings:
65
+ tree.add(f"⚠️ 发现 {len(warnings)} 个警告(不影响构建)")
66
+
67
+ console.print(tree)
68
+ return len(errors) == 0, errors
69
+
70
+ def check_configuration(directory: Path) -> Tuple[bool, List[str]]:
71
+ """检查 configure.json 文件"""
72
+ tree = Tree("📄 配置文件检查")
73
+ errors = []
74
+ config_path = directory / "config" / "configure.json"
75
+
76
+ if not config_path.exists():
77
+ tree.add("❌ 未找到 configure.json 文件")
78
+ console.print(tree)
79
+ return False, ["configure.json 文件不存在"]
80
+
81
+ try:
82
+ with open(config_path, 'r', encoding='utf-8') as f:
83
+ config = json.load(f)
84
+
85
+ required_fields = ["name", "version", "display_name"]
86
+ for field in required_fields:
87
+ if field not in config:
88
+ errors.append(f"configure.json 缺少必要字段: {field}")
89
+ tree.add(f"❌ 缺少字段: {field}")
90
+ else:
91
+ tree.add(f"✓ {field}: {config[field]}")
92
+
93
+ if errors:
94
+ tree.add("❌ 检查未通过")
95
+ else:
96
+ tree.add("✅ 检查通过")
97
+
98
+ console.print(tree)
99
+ return len(errors) == 0, errors
100
+ except json.JSONDecodeError:
101
+ tree.add("❌ 配置文件格式错误")
102
+ console.print(tree)
103
+ return False, ["configure.json 文件格式错误"]
104
+
105
+ def check_markdown_files(directory: Path) -> Tuple[bool, List[str]]:
106
+ """检查必要的 Markdown 文件"""
107
+ tree = Tree("📑 Markdown 文件检查")
108
+ errors = []
109
+
110
+ # 先读取配置文件中的 type 字段
111
+ config_path = directory / "config" / "configure.json"
112
+ config_type = "agent" # 默认值
113
+
114
+ if config_path.exists():
115
+ try:
116
+ with open(config_path, 'r', encoding='utf-8') as f:
117
+ config = json.load(f)
118
+ config_type = config.get("type", "agent")
119
+ except json.JSONDecodeError:
120
+ pass # 配置文件格式错误时使用默认值
121
+
122
+ # 根据 type 设置不同的 required_files
123
+ if config_type == "kit":
124
+ required_files = [
125
+ "configure.json",
126
+ "long_description.md",
127
+ "input.json"
128
+ ]
129
+ else: # type=agent 或空值
130
+ required_files = [
131
+ "initial_assistant_message.md",
132
+ "initial_system_prompt.md",
133
+ "long_description.md"
134
+ ]
135
+
136
+ tree.add(f"检查类型: {config_type}")
137
+
138
+ for file in required_files:
139
+ file_path = directory / "config" / file
140
+ if not file_path.exists():
141
+ errors.append(f"缺少必要文件: {file}")
142
+ tree.add(f"❌ {file}")
143
+ else:
144
+ # 对于 input.json,额外检查 JSON 格式
145
+ if file == "input.json":
146
+ try:
147
+ with open(file_path, 'r', encoding='utf-8') as f:
148
+ json.load(f)
149
+ tree.add(f"✓ {file} (JSON 格式正确)")
150
+ except json.JSONDecodeError:
151
+ errors.append(f"{file} JSON 格式错误")
152
+ tree.add(f"❌ {file} (JSON 格式错误)")
153
+ else:
154
+ tree.add(f"✓ {file}")
155
+
156
+ if errors:
157
+ tree.add("❌ 检查未通过")
158
+ else:
159
+ tree.add("✅ 检查通过")
160
+
161
+ console.print(tree)
162
+ return len(errors) == 0, errors
163
+
164
+ def create_zip_package(directory: Path) -> str:
165
+ """创建 zip 包"""
166
+ tree = Tree("📦 创建压缩包")
167
+ with open(directory / "config" / "configure.json", 'r', encoding='utf-8') as f:
168
+ config = json.load(f)
169
+
170
+ zip_name = f"{config['name']}_{config['version']}.zip"
171
+ zip_path = directory / zip_name
172
+
173
+ tree.add(f"包名: {zip_name}")
174
+
175
+ # 获取配置类型
176
+ config_type = config.get("type", "agent")
177
+
178
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
179
+ # 添加所有 Python 文件
180
+ py_files = list(directory.rglob('*.py'))
181
+ py_tree = tree.add("Python 文件")
182
+ for py_file in py_files:
183
+ if not py_file.name.startswith('_'):
184
+ zipf.write(py_file, py_file.relative_to(directory))
185
+ py_tree.add(f"+ {py_file.relative_to(directory)}")
186
+
187
+ # 添加配置文件
188
+ config_tree = tree.add("配置文件")
189
+ zipf.write(directory / "config" / "configure.json", "config/configure.json")
190
+ config_tree.add("+ config/configure.json")
191
+
192
+ # 添加 demos 目录
193
+ demos_tree = tree.add("Demos 文件")
194
+ demos_dir = directory / "demos"
195
+ if demos_dir.exists() and demos_dir.is_dir():
196
+ for demos_file in demos_dir.rglob('*'):
197
+ if demos_file.is_file():
198
+ zipf.write(demos_file, demos_file.relative_to(directory))
199
+ demos_tree.add(f"+ {demos_file.relative_to(directory)}")
200
+
201
+ # 根据类型添加不同的文件
202
+ md_tree = tree.add("其他文件")
203
+ if config_type == "kit":
204
+ # kit 类型需要添加的文件
205
+ other_files = ["long_description.md", "input.json"]
206
+ else:
207
+ # agent 类型需要添加的文件
208
+ other_files = ["initial_assistant_message.md", "initial_system_prompt.md", "long_description.md"]
209
+
210
+ for file in other_files:
211
+ file_path = directory / "config" / file
212
+ if file_path.exists():
213
+ zipf.write(file_path, f"config/{file}")
214
+ md_tree.add(f"+ config/{file}")
215
+
216
+ tree.add("✅ 压缩包创建完成")
217
+ console.print(tree)
218
+ return zip_name
219
+
220
+ def build_package(directory: Path) -> Tuple[bool, List[str], str]:
221
+ """构建项目包
222
+
223
+ Returns:
224
+ Tuple[bool, List[str], str]: (是否成功, 错误信息列表, zip包名称)
225
+ """
226
+ console.print(Panel.fit(
227
+ "[bold blue]🚀 开始构建项目包[/bold blue]",
228
+ border_style="blue"
229
+ ))
230
+
231
+ all_passed = True
232
+ all_errors = []
233
+
234
+ # 1. 检查 Python 文件
235
+ py_passed, py_errors = check_python_files(directory)
236
+ if not py_passed:
237
+ all_passed = False
238
+ all_errors.extend(py_errors)
239
+
240
+ # 2. 检查配置文件
241
+ config_passed, config_errors = check_configuration(directory)
242
+ if not config_passed:
243
+ all_passed = False
244
+ all_errors.extend(config_errors)
245
+
246
+ # 3. 检查 Markdown 文件
247
+ md_passed, md_errors = check_markdown_files(directory)
248
+ if not md_passed:
249
+ all_passed = False
250
+ all_errors.extend(md_errors)
251
+
252
+ # 如果所有检查都通过,创建 zip 包
253
+ zip_name = ""
254
+ if all_passed:
255
+ zip_name = create_zip_package(directory)
256
+
257
+ if all_passed:
258
+ console.print(Panel.fit(
259
+ f"[bold green]✅ 构建成功![/bold green]\n"
260
+ f"压缩包: {zip_name}",
261
+ border_style="green"
262
+ ))
263
+ else:
264
+ console.print(Panel.fit(
265
+ "[bold red]❌ 构建失败![/bold red]\n" + "\n".join(all_errors),
266
+ border_style="red"
267
+ ))
268
+
269
+ return all_passed, all_errors, zip_name
@@ -0,0 +1,48 @@
1
+ import click
2
+ import json
3
+ from pathlib import Path
4
+ from .parser import parse_directory
5
+ from .build import build_package
6
+ from .init import init
7
+
8
+ @click.group()
9
+ def cli():
10
+ """Adam Community CLI 工具"""
11
+ pass
12
+
13
+ @cli.command()
14
+ @click.argument('directory', type=click.Path(exists=True, file_okay=False, dir_okay=True), default='.')
15
+ def parse(directory):
16
+ """解析指定目录下的所有 Python 文件并生成 functions.json"""
17
+ directory_path = Path(directory)
18
+ all_functions = parse_directory(directory_path)
19
+
20
+ # 将结果写入 functions.json
21
+ output_file = directory_path / 'functions.json'
22
+ with open(output_file, 'w', encoding='utf-8') as f:
23
+ json.dump(all_functions, f, indent=2, ensure_ascii=False)
24
+
25
+ click.echo(f"已成功解析 {len(all_functions)} 个类,结果保存在 {output_file}")
26
+
27
+ @cli.command()
28
+ @click.argument('directory', type=click.Path(exists=True, file_okay=False, dir_okay=True), default='.')
29
+ def build(directory):
30
+ """构建项目包"""
31
+ directory_path = Path(directory)
32
+
33
+ # 执行构建
34
+ success, errors, zip_name = build_package(directory_path)
35
+
36
+ if success:
37
+ click.echo(f"包创建成功: {zip_name}")
38
+ else:
39
+ click.echo("检查未通过,发现以下问题:")
40
+ for error in errors:
41
+ click.echo(f"- {error}")
42
+ raise click.Abort()
43
+
44
+ # 添加 init 命令
45
+ cli.add_command(init)
46
+
47
+ if __name__ == '__main__':
48
+ cli()
@@ -0,0 +1,154 @@
1
+ import click
2
+ import re
3
+ from pathlib import Path
4
+ from jinja2 import Environment, FileSystemLoader
5
+ from typing import Dict, Any
6
+
7
+ @click.command()
8
+ @click.option('--name', prompt='项目名称(仅支持字母、数字、连字符,不能有空格)', help='项目的英文名称(用于文件夹和配置)')
9
+ @click.option('--display-name', prompt='显示名称', help='项目的中文显示名称')
10
+ @click.option('--description', prompt='项目描述', help='项目的简短描述')
11
+ @click.option('--version', default='1.0.0', prompt='版本号', help='项目版本号')
12
+ @click.option('--author', prompt='作者', help='项目作者')
13
+ @click.option('--type',
14
+ type=click.Choice(['kit', 'toolbox']),
15
+ prompt='项目类型',
16
+ help='选择项目类型: kit(表单工具) 或 toolbox(智能体工具)')
17
+ @click.argument('directory', type=click.Path(exists=True, file_okay=False, dir_okay=True), default='.')
18
+ def init(name: str, display_name: str, description: str, version: str, author: str, type: str, directory: str):
19
+ """初始化一个新的 Adam 工具项目"""
20
+
21
+ # 验证项目名称格式
22
+ if not validate_project_name(name):
23
+ click.echo(f"错误: 项目名称 '{name}' 格式不正确")
24
+ click.echo("项目名称只能包含字母、数字和连字符(-),不能包含空格或其他特殊字符")
25
+ click.echo("示例: my-tool, data-processor, image-analyzer")
26
+ return
27
+
28
+ directory_path = Path(directory)
29
+ project_path = directory_path / name
30
+
31
+ # 检查目录是否已存在
32
+ if project_path.exists():
33
+ click.echo(f"错误: 目录 '{name}' 已存在")
34
+ return
35
+
36
+ # 创建项目目录
37
+ project_path.mkdir(parents=True, exist_ok=True)
38
+ click.echo(f"创建项目目录: {project_path}")
39
+
40
+ # 创建config目录
41
+ config_path = project_path / "config"
42
+ config_path.mkdir(parents=True, exist_ok=True)
43
+
44
+ # 设置Jinja2环境
45
+ template_dir = Path(__file__).parent / "templates"
46
+ env = Environment(loader=FileSystemLoader(template_dir))
47
+
48
+ # 模板变量
49
+ template_vars = {
50
+ 'name': name,
51
+ 'display_name': display_name,
52
+ 'description': description,
53
+ 'version': version,
54
+ 'author': author,
55
+ 'project_type': type
56
+ }
57
+
58
+ # 生成配置文件
59
+ render_and_save(env, 'configure.json.j2', config_path / "configure.json", template_vars)
60
+ click.echo(f"生成配置文件: config/configure.json")
61
+
62
+ # 生成描述文件
63
+ render_and_save(env, 'long_description.md.j2', config_path / "long_description.md", template_vars)
64
+ click.echo(f"生成描述文件: config/long_description.md")
65
+
66
+ if type == 'kit':
67
+ generate_kit_files(env, project_path, config_path, template_vars)
68
+ else:
69
+ generate_toolbox_files(env, project_path, config_path, template_vars)
70
+
71
+ # 生成 Makefile
72
+ render_and_save(env, 'Makefile.j2', project_path / "Makefile", template_vars)
73
+ click.echo(f"生成构建脚本: Makefile")
74
+
75
+ # 生成 README 文件
76
+ if type == 'kit':
77
+ render_and_save(env, 'README_kit.md.j2', project_path / "README.md", template_vars)
78
+ else:
79
+ render_and_save(env, 'README_toolbox.md.j2', project_path / "README.md", template_vars)
80
+ click.echo(f"生成项目文档: README.md")
81
+
82
+ click.echo(f"\n✅ 项目 '{name}' 初始化完成!")
83
+ click.echo(f"📁 项目路径: {project_path}")
84
+ click.echo("\n📋 后续步骤:")
85
+ click.echo("1. 📖 阅读 README.md 了解详细的开发指南")
86
+ click.echo("2. 🔧 根据需要修改 Python 代码实现")
87
+ if type == 'kit':
88
+ click.echo("3. 📝 自定义 config/input.json 表单配置")
89
+ else:
90
+ click.echo("3. 🤖 自定义 config/initial_system_prompt.md 和 config/initial_assistant_message.md")
91
+ click.echo("4. 📄 完善 config/long_description.md 描述文档")
92
+ click.echo("5. ⚙️ 运行 'make parse' 生成 functions.json")
93
+ click.echo("6. 📦 运行 'make build' 打包项目")
94
+ click.echo(f"\n💡 详细的开发指南请查看: {project_path}/README.md")
95
+
96
+
97
+ def render_and_save(env: Environment, template_name: str, output_path: Path, template_vars: Dict[str, Any]):
98
+ """渲染模板并保存到文件"""
99
+ template = env.get_template(template_name)
100
+ content = template.render(**template_vars)
101
+ with open(output_path, 'w', encoding='utf-8') as f:
102
+ f.write(content)
103
+
104
+
105
+ def generate_kit_files(env: Environment, project_path: Path, config_path: Path, template_vars: Dict[str, Any]):
106
+ """生成 kit 项目的特定文件"""
107
+
108
+ # 生成 input.json 表单配置
109
+ render_and_save(env, 'input.json.j2', config_path / "input.json", template_vars)
110
+ click.echo(f"生成表单配置: config/input.json")
111
+
112
+ # 生成主要的Python实现文件
113
+ python_filename = f"{template_vars['name'].replace('-', '_')}.py"
114
+ render_and_save(env, 'kit_python.py.j2', project_path / python_filename, template_vars)
115
+ click.echo(f"生成主要实现文件: {python_filename}")
116
+
117
+
118
+ def generate_toolbox_files(env: Environment, project_path: Path, config_path: Path, template_vars: Dict[str, Any]):
119
+ """生成 toolbox 项目的特定文件"""
120
+
121
+ # 生成 initial_system_prompt.md
122
+ render_and_save(env, 'initial_system_prompt.md.j2', config_path / "initial_system_prompt.md", template_vars)
123
+ click.echo(f"生成系统提示文件: config/initial_system_prompt.md")
124
+
125
+ # 生成 initial_assistant_message.md
126
+ render_and_save(env, 'initial_assistant_message.md.j2', config_path / "initial_assistant_message.md", template_vars)
127
+ click.echo(f"生成助手消息文件: config/initial_assistant_message.md")
128
+
129
+ # 生成主要的Python实现文件
130
+ python_filename = f"{template_vars['name'].replace('-', '_')}.py"
131
+ render_and_save(env, 'toolbox_python.py.j2', project_path / python_filename, template_vars)
132
+ click.echo(f"生成主要实现文件: {python_filename}")
133
+
134
+
135
+ def validate_project_name(name: str) -> bool:
136
+ """验证项目名称格式"""
137
+ # 项目名称只能包含字母、数字和连字符,不能有空格
138
+ pattern = r'^[a-zA-Z0-9-]+$'
139
+ if not re.match(pattern, name):
140
+ return False
141
+
142
+ # 不能以连字符开始或结束
143
+ if name.startswith('-') or name.endswith('-'):
144
+ return False
145
+
146
+ # 不能有连续的连字符
147
+ if '--' in name:
148
+ return False
149
+
150
+ # 长度限制
151
+ if len(name) < 1 or len(name) > 50:
152
+ return False
153
+
154
+ return True