adam-community 1.0.25__py3-none-any.whl → 1.0.27__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.
@@ -1 +1 @@
1
- __version__ = "1.0.25"
1
+ __version__ = "1.0.27"
adam_community/cli/cli.py CHANGED
@@ -5,6 +5,7 @@ from .parser import parse_directory
5
5
  from .build import build_package
6
6
  from .init import init
7
7
  from .updater import check_and_notify_update, update_cli, set_update_disabled
8
+ from .sif_build import sif
8
9
  from ..__version__ import __version__
9
10
 
10
11
  @click.group()
@@ -76,5 +77,8 @@ def config(disable_update_check, enable_update_check):
76
77
  # 添加 init 命令
77
78
  cli.add_command(init)
78
79
 
80
+ # 添加 sif 命令组
81
+ cli.add_command(sif)
82
+
79
83
  if __name__ == '__main__':
80
84
  cli()
@@ -0,0 +1,577 @@
1
+ import click
2
+ import os
3
+ import subprocess
4
+ import sys
5
+ import re
6
+ import shutil
7
+ from pathlib import Path
8
+ from typing import Tuple, List, Optional
9
+ from rich.console import Console
10
+ from rich.panel import Panel
11
+
12
+ console = Console()
13
+
14
+
15
+ def validateSifFile(sif_path: Path) -> Tuple[bool, str]:
16
+ """验证 SIF 文件是否有效
17
+
18
+ Args:
19
+ sif_path: SIF 文件路径
20
+
21
+ Returns:
22
+ Tuple[bool, str]: (是否有效, 错误消息)
23
+ """
24
+ if not sif_path.exists():
25
+ return False, f"SIF 文件不存在: {sif_path}"
26
+
27
+ if not sif_path.is_file():
28
+ return False, f"路径不是文件: {sif_path}"
29
+
30
+ if not os.access(sif_path, os.R_OK):
31
+ return False, f"SIF 文件不可读: {sif_path}"
32
+
33
+ file_size = sif_path.stat().st_size
34
+ if file_size == 0:
35
+ return False, f"SIF 文件为空: {sif_path}"
36
+
37
+ return True, ""
38
+
39
+
40
+ def validateImageUrl(image_url: str) -> Tuple[bool, str]:
41
+ """验证 Docker 镜像 URL 格式
42
+
43
+ Args:
44
+ image_url: Docker 镜像 URL
45
+
46
+ Returns:
47
+ Tuple[bool, str]: (是否有效, 错误消息)
48
+ """
49
+ # 基本格式验证:registry/namespace/image:tag
50
+ # 支持域名和 IP 地址(带端口号)
51
+ pattern = r'^[a-zA-Z0-9\-\.]+(:[0-9]+)?(/[a-zA-Z0-9\-_]+)+:[a-zA-Z0-9\.\-_]+$'
52
+
53
+ if not re.match(pattern, image_url):
54
+ return False, "镜像 URL 格式不正确,应为 registry/namespace/image:tag"
55
+
56
+ return True, ""
57
+
58
+
59
+ def checkCommandAvailable(command: str) -> Tuple[bool, str, str]:
60
+ """检查命令是否可用
61
+
62
+ Args:
63
+ command: 命令名称
64
+
65
+ Returns:
66
+ Tuple[bool, str, str]: (是否可用, 安装提示, URL)
67
+ """
68
+ # 使用 which 命令检测命令是否存在(更可靠)
69
+ try:
70
+ result = subprocess.run(
71
+ ['which', command],
72
+ capture_output=True,
73
+ text=True,
74
+ timeout=5
75
+ )
76
+ if result.returncode == 0 and result.stdout.strip():
77
+ return True, "", ""
78
+ except (FileNotFoundError, subprocess.TimeoutExpired):
79
+ pass
80
+
81
+ # 如果 which 不可用,尝试直接运行命令
82
+ try:
83
+ # 对于 split,尝试运行一个简单的命令
84
+ if command == 'split':
85
+ # 使用 --help 而不是 --version(macOS 的 split 不支持 --version)
86
+ result = subprocess.run(
87
+ ['split', '--help'],
88
+ capture_output=True,
89
+ text=True,
90
+ timeout=5
91
+ )
92
+ if result.returncode == 0:
93
+ return True, "", ""
94
+ else:
95
+ # 其他命令尝试 --version
96
+ result = subprocess.run(
97
+ [command, '--version'],
98
+ capture_output=True,
99
+ text=True,
100
+ timeout=5
101
+ )
102
+ if result.returncode == 0:
103
+ return True, "", ""
104
+ except (FileNotFoundError, subprocess.TimeoutExpired):
105
+ pass
106
+
107
+ # 命令不可用,返回安装提示
108
+ install_hints = {
109
+ 'split': (
110
+ "split 命令未找到",
111
+ "split 是 macOS/Linux 系统自带命令\n\n"
112
+ "macOS: 已预装(如果提示缺少,请安装 Xcode Command Line Tools)\n"
113
+ " xcode-select --install\n\n"
114
+ "Linux: sudo apt-get install coreutils / sudo yum install coreutils"
115
+ ),
116
+ 'docker': (
117
+ "Docker 未安装或未运行",
118
+ "Docker 是容器化平台\n\n"
119
+ "macOS: 下载并安装 Docker Desktop\n"
120
+ " https://www.docker.com/products/docker-desktop/\n\n"
121
+ "Linux: 安装 Docker Engine\n"
122
+ " https://docs.docker.com/engine/install/\n\n"
123
+ "安装后请确保 Docker daemon 正在运行"
124
+ )
125
+ }
126
+
127
+ if command in install_hints:
128
+ hint, url = install_hints[command]
129
+ return False, hint, url
130
+
131
+ return False, f"{command} 命令未找到", ""
132
+
133
+
134
+ def checkDockerEnvironment() -> Tuple[bool, List[str]]:
135
+ """检查 Docker 是否可用
136
+
137
+ Returns:
138
+ Tuple[bool, List[str]]: (是否可用, 错误消息列表)
139
+ """
140
+ errors = []
141
+
142
+ # 检查 Docker 命令
143
+ docker_available, docker_hint, docker_url = checkCommandAvailable('docker')
144
+ if not docker_available:
145
+ errors.append(f"❌ {docker_hint}")
146
+ if docker_url:
147
+ errors.append(f"\n{docker_url}")
148
+ else:
149
+ # 检查 Docker daemon 是否运行
150
+ try:
151
+ result = subprocess.run(
152
+ ['docker', 'info'],
153
+ capture_output=True,
154
+ text=True,
155
+ timeout=5
156
+ )
157
+ if result.returncode != 0:
158
+ errors.append("\n⚠️ Docker daemon 未运行,请启动 Docker")
159
+ except Exception:
160
+ pass
161
+
162
+ return len(errors) == 0, errors
163
+
164
+
165
+ def checkRequiredCommands() -> Tuple[bool, List[str]]:
166
+ """检查所有必需的命令
167
+
168
+ Returns:
169
+ Tuple[bool, List[str]]: (是否全部可用, 错误消息列表)
170
+ """
171
+ all_errors = []
172
+
173
+ # 检查 split 命令
174
+ split_available, split_hint, split_url = checkCommandAvailable('split')
175
+ if not split_available:
176
+ error_msg = f"❌ {split_hint}"
177
+ if split_url:
178
+ error_msg += f"\n\n{split_url}"
179
+ all_errors.append(error_msg)
180
+
181
+ # 检查 Docker
182
+ docker_available, docker_errors = checkDockerEnvironment()
183
+ if not docker_available:
184
+ all_errors.extend(docker_errors)
185
+
186
+ return len(all_errors) == 0, all_errors
187
+
188
+
189
+ def createWorkDir(sif_path: Path) -> Path:
190
+ """创建临时工作目录
191
+
192
+ Args:
193
+ sif_path: SIF 文件路径
194
+
195
+ Returns:
196
+ Path: 工作目录路径
197
+ """
198
+ parent_dir = sif_path.parent
199
+ work_dir = parent_dir / ".sif_build_temp"
200
+ work_dir.mkdir(parents=True, exist_ok=True)
201
+ return work_dir
202
+
203
+
204
+ def calculateOptimalChunkSize(file_size_bytes: int) -> Optional[str]:
205
+ """根据文件大小自适应计算切片大小
206
+
207
+ Args:
208
+ file_size_bytes: 文件大小(字节)
209
+
210
+ Returns:
211
+ Optional[str]: 切片大小(如 '100M', '500M'),None 表示不切片
212
+ """
213
+ size_mb = file_size_bytes / (1024 * 1024)
214
+
215
+ if size_mb < 500:
216
+ return None # 不切片
217
+ elif size_mb < 2 * 1024:
218
+ return "100M"
219
+ elif size_mb < 10 * 1024:
220
+ return "500M"
221
+ else:
222
+ return "1G"
223
+
224
+
225
+ def splitSifFile(sif_path: Path, chunk_size: Optional[str], work_dir: Path) -> List[Path]:
226
+ """切片 SIF 文件
227
+
228
+ Args:
229
+ sif_path: SIF 文件路径
230
+ chunk_size: 切片大小(如 '100M'),None 表示不切片
231
+ work_dir: 工作目录
232
+
233
+ Returns:
234
+ List[Path]: 切片文件列表
235
+
236
+ Raises:
237
+ subprocess.CalledProcessError: split 命令执行失败
238
+ """
239
+ if chunk_size is None:
240
+ # 不切片,直接复制到工作目录
241
+ dest_file = work_dir / sif_path.name
242
+ shutil.copy2(sif_path, dest_file)
243
+ return [dest_file]
244
+
245
+ # 使用 split 命令切片
246
+ output_prefix = sif_path.name # 不包含路径
247
+ cmd = ['split', '-b', chunk_size, '-d', str(sif_path), output_prefix + '.']
248
+
249
+ result = subprocess.run(
250
+ cmd,
251
+ cwd=work_dir,
252
+ capture_output=True,
253
+ text=True,
254
+ check=True
255
+ )
256
+
257
+ # 查找所有切片文件
258
+ chunks = sorted(work_dir.glob(f"{output_prefix}.*"))
259
+ return chunks
260
+
261
+
262
+ def generateDockerfile(work_dir: Path) -> Path:
263
+ """生成 Dockerfile
264
+
265
+ Args:
266
+ work_dir: 工作目录
267
+
268
+ Returns:
269
+ Path: Dockerfile 文件路径
270
+ """
271
+ dockerfile_path = work_dir / "Dockerfile"
272
+
273
+ # 使用 DaoCloud 镜像加速,解决国内网络访问 Docker Hub 的问题
274
+ dockerfile_content = """FROM docker.m.daocloud.io/library/alpine
275
+ COPY . /sif
276
+ """
277
+
278
+ with open(dockerfile_path, 'w', encoding='utf-8') as f:
279
+ f.write(dockerfile_content)
280
+
281
+ return dockerfile_path
282
+
283
+
284
+ def executeCommand(cmd: List[str], description: str, console: Console) -> bool:
285
+ """执行命令并实时显示输出
286
+
287
+ Args:
288
+ cmd: 命令列表
289
+ description: 命令描述
290
+ console: Console 实例
291
+
292
+ Returns:
293
+ bool: 是否执行成功
294
+ """
295
+ console.print(f"\n[dim]执行命令: {' '.join(cmd)}[/dim]")
296
+
297
+ try:
298
+ process = subprocess.Popen(
299
+ cmd,
300
+ stdout=subprocess.PIPE,
301
+ stderr=subprocess.STDOUT,
302
+ universal_newlines=True,
303
+ bufsize=1
304
+ )
305
+
306
+ # 实时显示输出
307
+ for line in process.stdout:
308
+ console.print(line.rstrip())
309
+
310
+ process.wait()
311
+ return process.returncode == 0
312
+
313
+ except Exception as e:
314
+ console.print(f"[red]命令执行异常: {str(e)}[/red]")
315
+ return False
316
+
317
+
318
+ def buildDockerImage(work_dir: Path, image_url: str, console: Console) -> bool:
319
+ """构建 Docker 镜像
320
+
321
+ Args:
322
+ work_dir: 工作目录
323
+ image_url: 镜像 URL
324
+ console: Console 实例
325
+
326
+ Returns:
327
+ bool: 是否构建成功
328
+ """
329
+ # 指定架构为 x86_64,确保在不同平台上的兼容性
330
+ cmd = ['docker', 'build', '--platform', 'linux/amd64', '-t', image_url, str(work_dir)]
331
+ return executeCommand(cmd, "构建 Docker 镜像", console)
332
+
333
+
334
+ def pushDockerImage(image_url: str, username: Optional[str], password: Optional[str], console: Console) -> bool:
335
+ """推送 Docker 镜像
336
+
337
+ Args:
338
+ image_url: 镜像 URL
339
+ username: 用户名
340
+ password: 密码
341
+ console: Console 实例
342
+
343
+ Returns:
344
+ bool: 是否推送成功
345
+ """
346
+ # 如果提供了认证信息,先执行 docker login
347
+ if username and password:
348
+ console.print("\n[bold blue]🔐 登录 Docker 仓库[/bold blue]")
349
+
350
+ # 从镜像 URL 提取 registry
351
+ registry = image_url.split('/')[0]
352
+
353
+ # 使用 stdin 传递密码
354
+ cmd = ['docker', 'login', '-u', username, '--password-stdin', registry]
355
+
356
+ try:
357
+ process = subprocess.Popen(
358
+ cmd,
359
+ stdin=subprocess.PIPE,
360
+ stdout=subprocess.PIPE,
361
+ stderr=subprocess.PIPE,
362
+ universal_newlines=True
363
+ )
364
+
365
+ stdout, stderr = process.communicate(input=password)
366
+
367
+ if process.returncode != 0:
368
+ console.print(f"[red]登录失败: {stderr}[/red]")
369
+ return False
370
+
371
+ console.print("[green]✓ 登录成功[/green]")
372
+ except Exception as e:
373
+ console.print(f"[red]登录异常: {str(e)}[/red]")
374
+ return False
375
+
376
+ # 推送镜像
377
+ cmd = ['docker', 'push', image_url]
378
+ return executeCommand(cmd, "推送 Docker 镜像", console)
379
+
380
+
381
+ def cleanupTempFiles(work_dir: Path, keep_temp: bool, console: Console):
382
+ """清理临时文件
383
+
384
+ Args:
385
+ work_dir: 工作目录
386
+ keep_temp: 是否保留临时文件
387
+ console: Console 实例
388
+ """
389
+ if keep_temp:
390
+ console.print(f"\n[dim]临时文件保留在: {work_dir}[/dim]")
391
+ return
392
+
393
+ console.print(f"\n[bold blue]🧹 清理临时文件[/bold blue]")
394
+
395
+ try:
396
+ shutil.rmtree(work_dir)
397
+ console.print(f"[green]✓ 已清理: {work_dir}[/green]")
398
+ except Exception as e:
399
+ console.print(f"[yellow]⚠️ 清理失败: {str(e)}[/yellow]")
400
+
401
+
402
+ @click.group()
403
+ def sif():
404
+ """SIF 文件管理命令"""
405
+ pass
406
+
407
+
408
+ @sif.command(name='upload')
409
+ @click.argument('sif_file', type=click.Path(exists=True))
410
+ @click.argument('image_url')
411
+ @click.option('--username', help='Docker 仓库用户名')
412
+ @click.option('--password', help='Docker 仓库密码')
413
+ @click.option('--chunk-size', help='覆盖自适应计算的切片大小(如 100M, 500M)')
414
+ @click.option('--keep-temp', is_flag=True, help='保留临时文件')
415
+ def upload(sif_file, image_url, username, password, chunk_size, keep_temp):
416
+ """将 SIF 文件切片并构建 Docker 镜像推送到仓库
417
+
418
+ 切片策略:
419
+ - 文件 < 500MB:不切片,直接使用原文件
420
+ - 文件 500MB-2GB:切片大小 100MB
421
+ - 文件 2GB-10GB:切片大小 500MB
422
+ - 文件 > 10GB:切片大小 1GB
423
+
424
+ 可通过 --chunk-size 参数覆盖自适应策略
425
+
426
+ 示例:
427
+ adam-cli sif upload ./xxx.sif xxx.cn-hangzhou.cr.aliyuncs.com/openscore/openscore-core:1.0.0
428
+ adam-cli sif upload ./xxx.sif registry.example.com/myimage:latest --username user --password pass
429
+ """
430
+ sif_path = Path(sif_file).resolve()
431
+ file_size = sif_path.stat().st_size
432
+ file_size_mb = file_size / (1024 * 1024)
433
+
434
+ # 显示开始面板
435
+ console.print(Panel.fit(
436
+ f"[bold blue]🚀 开始构建 SIF Docker 镜像[/bold blue]\n"
437
+ f"SIF 文件: {sif_path.name}\n"
438
+ f"文件大小: {file_size_mb:.2f} MB\n"
439
+ f"目标镜像: {image_url}",
440
+ border_style="blue"
441
+ ))
442
+
443
+ work_dir = None
444
+
445
+ try:
446
+ # ===== 步骤 1: 验证环境 =====
447
+ console.print("\n[bold blue]📦 步骤 1/5: 验证环境[/bold blue]")
448
+
449
+ # 验证 SIF 文件
450
+ valid, error_msg = validateSifFile(sif_path)
451
+ if not valid:
452
+ console.print(Panel.fit(
453
+ f"[bold red]❌ SIF 文件验证失败[/bold red]\n{error_msg}",
454
+ border_style="red"
455
+ ))
456
+ sys.exit(1)
457
+ console.print(" ✓ SIF 文件可读")
458
+
459
+ # 验证镜像 URL
460
+ valid, error_msg = validateImageUrl(image_url)
461
+ if not valid:
462
+ console.print(Panel.fit(
463
+ f"[bold red]❌ 镜像 URL 验证失败[/bold red]\n{error_msg}",
464
+ border_style="red"
465
+ ))
466
+ sys.exit(1)
467
+ console.print(" ✓ 镜像 URL 格式正确")
468
+
469
+ # 检查所有必需的命令
470
+ all_available, errors = checkRequiredCommands()
471
+ if not all_available:
472
+ console.print(Panel.fit(
473
+ "[bold red]❌ 环境检查失败[/bold red]\n"
474
+ + "\n".join(errors),
475
+ border_style="red"
476
+ ))
477
+ sys.exit(1)
478
+ console.print(" ✓ split 命令可用")
479
+ console.print(" ✓ Docker 已安装并运行")
480
+
481
+ # ===== 步骤 2: 创建工作目录 =====
482
+ console.print("\n[bold blue]📦 步骤 2/5: 创建工作目录[/bold blue]")
483
+ work_dir = createWorkDir(sif_path)
484
+ console.print(f" ✓ 工作目录: {work_dir}")
485
+
486
+ # ===== 步骤 3: 切片 SIF 文件 =====
487
+ console.print("\n[bold blue]📦 步骤 3/5: 切片 SIF 文件[/bold blue]")
488
+
489
+ # 计算切片大小
490
+ if chunk_size:
491
+ actual_chunk_size = chunk_size
492
+ console.print(f" 切片策略: 自定义 ({chunk_size})")
493
+ else:
494
+ actual_chunk_size = calculateOptimalChunkSize(file_size)
495
+ if actual_chunk_size:
496
+ console.print(f" 切片策略: 自适应 ({actual_chunk_size})")
497
+ else:
498
+ console.print(f" 切片策略: 不切片 (文件 < 500MB)")
499
+
500
+ console.print(f" 文件大小: {file_size_mb:.2f} MB")
501
+
502
+ # 执行切片
503
+ try:
504
+ chunks = splitSifFile(sif_path, actual_chunk_size, work_dir)
505
+ console.print(f" ✓ 切片完成: {len(chunks)} 个文件")
506
+
507
+ # 显示切片详情
508
+ console.print(f"\n 📄 切片详情:")
509
+ for chunk in chunks:
510
+ chunk_size_mb = chunk.stat().st_size / (1024 * 1024)
511
+ console.print(f" - {chunk.name} ({chunk_size_mb:.2f} MB)")
512
+ except subprocess.CalledProcessError as e:
513
+ console.print(Panel.fit(
514
+ f"[bold red]❌ SIF 文件切片失败[/bold red]\n"
515
+ f"错误: {e.stderr}",
516
+ border_style="red"
517
+ ))
518
+ cleanupTempFiles(work_dir, keep_temp, console)
519
+ sys.exit(1)
520
+
521
+ # ===== 步骤 4: 生成 Dockerfile =====
522
+ console.print("\n[bold blue]📦 步骤 4/5: 生成 Dockerfile[/bold blue]")
523
+ dockerfile_path = generateDockerfile(work_dir)
524
+ console.print(f" ✓ Dockerfile 已生成")
525
+
526
+ # ===== 步骤 5: 构建 Docker 镜像 =====
527
+ console.print("\n[bold blue]📦 步骤 5/5: 构建 Docker 镜像[/bold blue]")
528
+
529
+ if not buildDockerImage(work_dir, image_url, console):
530
+ console.print(Panel.fit(
531
+ f"[bold red]❌ Docker 镜像构建失败[/bold red]",
532
+ border_style="red"
533
+ ))
534
+ cleanupTempFiles(work_dir, keep_temp, console)
535
+ sys.exit(1)
536
+
537
+ console.print("[green] ✓ 镜像构建成功[/green]")
538
+
539
+ # ===== 步骤 6: 推送 Docker 镜像 =====
540
+ console.print("\n[bold blue]📦 步骤 6/6: 推送 Docker 镜像[/bold blue]")
541
+
542
+ if not pushDockerImage(image_url, username, password, console):
543
+ console.print(Panel.fit(
544
+ f"[bold red]❌ Docker 镜像推送失败[/bold red]\n"
545
+ f"请检查网络连接和仓库认证信息",
546
+ border_style="red"
547
+ ))
548
+ cleanupTempFiles(work_dir, keep_temp, console)
549
+ sys.exit(1)
550
+
551
+ console.print("[green] ✓ 镜像推送成功[/green]")
552
+
553
+ # ===== 成功 =====
554
+ console.print(Panel.fit(
555
+ f"[bold green]✅ 构建成功![/bold green]\n"
556
+ f"镜像: {image_url}\n"
557
+ f"大小: {file_size_mb:.2f} MB\n"
558
+ f"切片数: {len(chunks)}",
559
+ border_style="green"
560
+ ))
561
+
562
+ # 清理临时文件
563
+ cleanupTempFiles(work_dir, keep_temp, console)
564
+
565
+ except Exception as e:
566
+ console.print(Panel.fit(
567
+ f"[bold red]❌ 执行过程中出现异常[/bold red]\n"
568
+ f"错误: {str(e)}",
569
+ border_style="red"
570
+ ))
571
+ if work_dir:
572
+ cleanupTempFiles(work_dir, keep_temp, console)
573
+ sys.exit(1)
574
+
575
+
576
+ if __name__ == '__main__':
577
+ sifBuild()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: adam_community
3
- Version: 1.0.25
3
+ Version: 1.0.27
4
4
  Summary: Adam Community Tools and Utilities
5
5
  Home-page: https://github.com/yourusername/adam-community
6
6
  Author: Adam Community
@@ -67,6 +67,23 @@ adam-cli build .
67
67
  adam-cli update
68
68
  ```
69
69
 
70
+ #### SIF 文件管理
71
+
72
+ 管理 SIF 文件,包括上传到 Docker 镜像仓库等操作:
73
+
74
+ ```bash
75
+ # 查看帮助
76
+ adam-cli sif --help
77
+
78
+ # 上传 SIF 文件到镜像仓库(自适应切片)
79
+ adam-cli sif upload ./xxx.sif registry.example.com/image:1.0.0
80
+
81
+ # 带认证上传
82
+ adam-cli sif upload ./app.sif registry.cn-hangzhou.aliyuncs.com/ns/app:latest \
83
+ --username user --password pass
84
+
85
+ ```
86
+
70
87
  ### Python 模块导入
71
88
 
72
89
  ```python
@@ -116,6 +133,7 @@ trackPath("/path/to/cache")
116
133
  - **项目构建**: 检查配置文件、文档文件并创建 zip 包
117
134
  - **类型检查**: 支持多种 Python 类型注解格式
118
135
  - **自动更新**: 智能检查和更新到最新版本,支持用户配置
136
+ - **SIF 镜像构建**: 将 SIF 文件切片并构建 Docker 镜像推送到仓库
119
137
 
120
138
  ## 开发
121
139
 
@@ -1,12 +1,13 @@
1
1
  adam_community/__init__.py,sha256=vAmF9VQR6D4peppH0hnrHDmZK5cFeFPh11GIsTKUXhE,429
2
- adam_community/__version__.py,sha256=_TgC2mrlgs6XxMzx9bzihItIy81yZaza2GnTmMNF5EA,23
2
+ adam_community/__version__.py,sha256=BFoP77JSRWYw9boz6i1KHik7kj9lxXXrcX2G2k1cWrc,23
3
3
  adam_community/tool.py,sha256=F6jxRU3urqTfgjLIZSW-hVWyj0FpNwvY65jOODXI19w,4954
4
4
  adam_community/util.py,sha256=SDXnWLHLfJxEJ5WBnwNq_FeHNwXxGK_F36dpI_hVkNc,17766
5
5
  adam_community/cli/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
6
6
  adam_community/cli/build.py,sha256=fCteEXjtU2ZsXXUWa-j61gh_JVU-6xSAH_LpOP5swFc,12623
7
- adam_community/cli/cli.py,sha256=xlPvn0aq3TpAPjA7z9shsCqR1aHDVtZuhvtc_SNA_cQ,2811
7
+ adam_community/cli/cli.py,sha256=UMJo6olpWF4D99_xYZ6n8ztdcVUFf8n48Lroy568G8g,2883
8
8
  adam_community/cli/init.py,sha256=JiRjUkYVnha6Oz-eQ9BgB0nEN6y-tkrNXfy3s342_74,9717
9
9
  adam_community/cli/parser.py,sha256=LWYVW69z4ICFXgvD5Vtcy1P-rEUxV_Rs4X96n34i3gE,17732
10
+ adam_community/cli/sif_build.py,sha256=HJWN_iw0sAOQO1bF4QaRJDAMmA8v8GEjiUtpdQG18C4,17825
10
11
  adam_community/cli/updater.py,sha256=zN521c-G20MKz63wm7h16quBxiEZp4vQ6AbyV-IqtXk,6304
11
12
  adam_community/cli/templates/Makefile.j2,sha256=arpo9AzOZTmjxIYiya9S_G_ldHYVVvf4cVOxNooQeGs,113
12
13
  adam_community/cli/templates/README_agent.md.j2,sha256=lbhaEPZrgbCfUG-T7GItkgfIV9h1rqxyfRQuGhcdOqU,8901
@@ -25,8 +26,8 @@ adam_community/cli/templates/long_description.md.j2,sha256=Rj6hcuNzEL0Sp17GQVCRJ
25
26
  adam_community/cli/templates/long_description_en.md.j2,sha256=xSbahwGarXlWopZqHw7lrcv1dQuvwj2ChhZv5pJmUy4,1725
26
27
  adam_community/cli/templates/rag_python.py.j2,sha256=YJL7-WIx-Dumt7lHuUGxl3Rbaw0kpkh8hpcCJ5lz9lA,2494
27
28
  adam_community/cli/templates/toolbox_python.py.j2,sha256=EOnmsJUvQRrcO7K7c88kI42gMmcM0Z4ab46qwOJXbH8,4192
28
- adam_community-1.0.25.dist-info/METADATA,sha256=3i_FpqlCX-IHuep5VdeEkel5JFB6MD13no1QsuY_3MY,3151
29
- adam_community-1.0.25.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
30
- adam_community-1.0.25.dist-info/entry_points.txt,sha256=4I7yRkn7cHwPY8-fWQLeAvKjc24zUy8Z65VsZNs0Wos,56
31
- adam_community-1.0.25.dist-info/top_level.txt,sha256=MS8jbePXKZChih9kGizNVX0I1MFZFGWBMCIW_r86qhU,15
32
- adam_community-1.0.25.dist-info/RECORD,,
29
+ adam_community-1.0.27.dist-info/METADATA,sha256=XTzwdHAGsX0lQ1GMZxNEbZS9aExZGBgPLMfEgtKOv9g,3628
30
+ adam_community-1.0.27.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
31
+ adam_community-1.0.27.dist-info/entry_points.txt,sha256=4I7yRkn7cHwPY8-fWQLeAvKjc24zUy8Z65VsZNs0Wos,56
32
+ adam_community-1.0.27.dist-info/top_level.txt,sha256=MS8jbePXKZChih9kGizNVX0I1MFZFGWBMCIW_r86qhU,15
33
+ adam_community-1.0.27.dist-info/RECORD,,