devsync 0.5.5__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 (84) hide show
  1. aiconfigkit/__init__.py +0 -0
  2. aiconfigkit/__main__.py +6 -0
  3. aiconfigkit/ai_tools/__init__.py +0 -0
  4. aiconfigkit/ai_tools/base.py +236 -0
  5. aiconfigkit/ai_tools/capability_registry.py +262 -0
  6. aiconfigkit/ai_tools/claude.py +91 -0
  7. aiconfigkit/ai_tools/claude_desktop.py +97 -0
  8. aiconfigkit/ai_tools/cline.py +92 -0
  9. aiconfigkit/ai_tools/copilot.py +92 -0
  10. aiconfigkit/ai_tools/cursor.py +109 -0
  11. aiconfigkit/ai_tools/detector.py +169 -0
  12. aiconfigkit/ai_tools/kiro.py +85 -0
  13. aiconfigkit/ai_tools/mcp_syncer.py +291 -0
  14. aiconfigkit/ai_tools/roo.py +110 -0
  15. aiconfigkit/ai_tools/translator.py +390 -0
  16. aiconfigkit/ai_tools/winsurf.py +102 -0
  17. aiconfigkit/cli/__init__.py +0 -0
  18. aiconfigkit/cli/delete.py +118 -0
  19. aiconfigkit/cli/download.py +274 -0
  20. aiconfigkit/cli/install.py +237 -0
  21. aiconfigkit/cli/install_new.py +937 -0
  22. aiconfigkit/cli/list.py +275 -0
  23. aiconfigkit/cli/main.py +454 -0
  24. aiconfigkit/cli/mcp_configure.py +232 -0
  25. aiconfigkit/cli/mcp_install.py +166 -0
  26. aiconfigkit/cli/mcp_sync.py +165 -0
  27. aiconfigkit/cli/package.py +383 -0
  28. aiconfigkit/cli/package_create.py +323 -0
  29. aiconfigkit/cli/package_install.py +472 -0
  30. aiconfigkit/cli/template.py +19 -0
  31. aiconfigkit/cli/template_backup.py +261 -0
  32. aiconfigkit/cli/template_init.py +499 -0
  33. aiconfigkit/cli/template_install.py +261 -0
  34. aiconfigkit/cli/template_list.py +172 -0
  35. aiconfigkit/cli/template_uninstall.py +146 -0
  36. aiconfigkit/cli/template_update.py +225 -0
  37. aiconfigkit/cli/template_validate.py +234 -0
  38. aiconfigkit/cli/tools.py +47 -0
  39. aiconfigkit/cli/uninstall.py +125 -0
  40. aiconfigkit/cli/update.py +309 -0
  41. aiconfigkit/core/__init__.py +0 -0
  42. aiconfigkit/core/checksum.py +211 -0
  43. aiconfigkit/core/component_detector.py +905 -0
  44. aiconfigkit/core/conflict_resolution.py +329 -0
  45. aiconfigkit/core/git_operations.py +539 -0
  46. aiconfigkit/core/mcp/__init__.py +1 -0
  47. aiconfigkit/core/mcp/credentials.py +279 -0
  48. aiconfigkit/core/mcp/manager.py +308 -0
  49. aiconfigkit/core/mcp/set_manager.py +1 -0
  50. aiconfigkit/core/mcp/validator.py +1 -0
  51. aiconfigkit/core/models.py +1661 -0
  52. aiconfigkit/core/package_creator.py +743 -0
  53. aiconfigkit/core/package_manifest.py +248 -0
  54. aiconfigkit/core/repository.py +298 -0
  55. aiconfigkit/core/secret_detector.py +438 -0
  56. aiconfigkit/core/template_manifest.py +283 -0
  57. aiconfigkit/core/version.py +201 -0
  58. aiconfigkit/storage/__init__.py +0 -0
  59. aiconfigkit/storage/library.py +429 -0
  60. aiconfigkit/storage/mcp_tracker.py +1 -0
  61. aiconfigkit/storage/package_tracker.py +234 -0
  62. aiconfigkit/storage/template_library.py +229 -0
  63. aiconfigkit/storage/template_tracker.py +296 -0
  64. aiconfigkit/storage/tracker.py +416 -0
  65. aiconfigkit/tui/__init__.py +5 -0
  66. aiconfigkit/tui/installer.py +511 -0
  67. aiconfigkit/utils/__init__.py +0 -0
  68. aiconfigkit/utils/atomic_write.py +90 -0
  69. aiconfigkit/utils/backup.py +169 -0
  70. aiconfigkit/utils/dotenv.py +128 -0
  71. aiconfigkit/utils/git_helpers.py +187 -0
  72. aiconfigkit/utils/logging.py +60 -0
  73. aiconfigkit/utils/namespace.py +134 -0
  74. aiconfigkit/utils/paths.py +205 -0
  75. aiconfigkit/utils/project.py +109 -0
  76. aiconfigkit/utils/streaming.py +216 -0
  77. aiconfigkit/utils/ui.py +194 -0
  78. aiconfigkit/utils/validation.py +187 -0
  79. devsync-0.5.5.dist-info/LICENSE +21 -0
  80. devsync-0.5.5.dist-info/METADATA +477 -0
  81. devsync-0.5.5.dist-info/RECORD +84 -0
  82. devsync-0.5.5.dist-info/WHEEL +5 -0
  83. devsync-0.5.5.dist-info/entry_points.txt +2 -0
  84. devsync-0.5.5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,383 @@
1
+ """Package CLI commands."""
2
+
3
+ from pathlib import Path
4
+ from typing import Optional
5
+
6
+ import typer
7
+ from rich.console import Console
8
+ from rich.table import Table
9
+
10
+ from aiconfigkit.cli.package_create import create_package_command
11
+ from aiconfigkit.cli.package_install import InstallationResult, install_package
12
+ from aiconfigkit.core.models import (
13
+ AIToolType,
14
+ ConflictResolution,
15
+ InstallationScope,
16
+ InstallationStatus,
17
+ )
18
+ from aiconfigkit.storage.package_tracker import PackageTracker
19
+ from aiconfigkit.utils.project import find_project_root
20
+
21
+ console = Console()
22
+ package_app = typer.Typer(help="Manage configuration packages")
23
+
24
+ # Register create command
25
+ package_app.command(name="create")(create_package_command)
26
+
27
+
28
+ @package_app.command(name="install")
29
+ def install_package_command(
30
+ package_path: str = typer.Argument(
31
+ ...,
32
+ help="Path to package directory containing manifest",
33
+ ),
34
+ target_ide: str = typer.Option(
35
+ "claude",
36
+ "--ide",
37
+ "-i",
38
+ help="Target IDE (claude, cursor, windsurf, copilot)",
39
+ ),
40
+ project: Optional[str] = typer.Option(
41
+ None,
42
+ "--project",
43
+ "-p",
44
+ help="Project root directory (defaults to current directory)",
45
+ ),
46
+ conflict: str = typer.Option(
47
+ "skip",
48
+ "--conflict",
49
+ "-c",
50
+ help="Conflict resolution strategy (skip, overwrite, rename)",
51
+ ),
52
+ force: bool = typer.Option(
53
+ False,
54
+ "--force",
55
+ "-f",
56
+ help="Force reinstallation even if already installed",
57
+ ),
58
+ quiet: bool = typer.Option(
59
+ False,
60
+ "--quiet",
61
+ "-q",
62
+ help="Minimal output",
63
+ ),
64
+ json_output: bool = typer.Option(
65
+ False,
66
+ "--json",
67
+ help="Output results as JSON",
68
+ ),
69
+ ) -> None:
70
+ """
71
+ Install a configuration package to a project.
72
+
73
+ Package must contain an ai-config-kit-package.yaml manifest.
74
+
75
+ Example:
76
+ aiconfig package install ./python-dev-setup --ide claude
77
+ aiconfig package install ~/packages/my-package --ide cursor --conflict overwrite
78
+ """
79
+ try:
80
+ # Parse target IDE
81
+ try:
82
+ ide_type = AIToolType(target_ide.lower())
83
+ except ValueError:
84
+ console.print(
85
+ f"[red]Error: Invalid IDE '{target_ide}'. " f"Valid options: claude, cursor, windsurf, copilot[/red]"
86
+ )
87
+ raise typer.Exit(1)
88
+
89
+ # Parse conflict resolution
90
+ try:
91
+ conflict_resolution = ConflictResolution(conflict.lower())
92
+ except ValueError:
93
+ console.print(
94
+ f"[red]Error: Invalid conflict resolution '{conflict}'. "
95
+ f"Valid options: skip, overwrite, rename[/red]"
96
+ )
97
+ raise typer.Exit(1)
98
+
99
+ # Determine project root
100
+ if project:
101
+ project_root = Path(project).resolve()
102
+ if not project_root.exists():
103
+ console.print(f"[red]Error: Project directory not found: {project}[/red]")
104
+ raise typer.Exit(1)
105
+ else:
106
+ project_root_maybe = find_project_root()
107
+ if not project_root_maybe:
108
+ console.print("[red]Error: Could not find project root. " "Use --project to specify explicitly.[/red]")
109
+ raise typer.Exit(1)
110
+ project_root = project_root_maybe
111
+
112
+ # Resolve package path
113
+ pkg_path = Path(package_path).resolve()
114
+ if not pkg_path.exists():
115
+ console.print(f"[red]Error: Package directory not found: {package_path}[/red]")
116
+ raise typer.Exit(1)
117
+
118
+ if not quiet:
119
+ console.print(f"[cyan]Installing package from {pkg_path}...[/cyan]")
120
+ console.print(f"[cyan]Target IDE: {ide_type.value}[/cyan]")
121
+ console.print(f"[cyan]Project root: {project_root}[/cyan]")
122
+
123
+ # Install package
124
+ result = install_package(
125
+ package_path=pkg_path,
126
+ project_root=project_root,
127
+ target_ide=ide_type,
128
+ scope=InstallationScope.PROJECT,
129
+ conflict_resolution=conflict_resolution,
130
+ force=force,
131
+ )
132
+
133
+ # Output results
134
+ if json_output:
135
+ import json
136
+
137
+ output = {
138
+ "success": result.success,
139
+ "status": result.status.value,
140
+ "package_name": result.package_name,
141
+ "version": result.version,
142
+ "installed_count": result.installed_count,
143
+ "skipped_count": result.skipped_count,
144
+ "failed_count": result.failed_count,
145
+ "components_installed": {k.value: v for k, v in result.components_installed.items()},
146
+ "is_reinstall": result.is_reinstall,
147
+ "error_message": result.error_message,
148
+ }
149
+ console.print(json.dumps(output, indent=2))
150
+ else:
151
+ _display_installation_summary(result, quiet)
152
+
153
+ # Exit with appropriate code
154
+ if not result.success:
155
+ raise typer.Exit(1)
156
+
157
+ except Exception as e:
158
+ console.print(f"[red]Installation failed: {e}[/red]")
159
+ raise typer.Exit(1)
160
+
161
+
162
+ def _display_installation_summary(result: InstallationResult, quiet: bool) -> None:
163
+ """Display installation summary to user."""
164
+ if result.success:
165
+ # Success message
166
+ if result.status == InstallationStatus.COMPLETE:
167
+ console.print(f"\n[green]✓ Successfully installed {result.package_name} v{result.version}[/green]")
168
+ elif result.status == InstallationStatus.PARTIAL:
169
+ console.print(f"\n[yellow]⚠ Partially installed {result.package_name} v{result.version}[/yellow]")
170
+ else:
171
+ console.print(f"\n[red]✗ Installation failed for {result.package_name} v{result.version}[/red]")
172
+
173
+ if result.is_reinstall:
174
+ console.print("[cyan] (Reinstalled existing package)[/cyan]")
175
+
176
+ # Component summary table
177
+ if not quiet:
178
+ table = Table(title="Installation Summary", show_header=True)
179
+ table.add_column("Component Type", style="cyan")
180
+ table.add_column("Count", justify="right", style="green")
181
+
182
+ for component_type, count in result.components_installed.items():
183
+ table.add_row(component_type.value, str(count))
184
+
185
+ console.print()
186
+ console.print(table)
187
+
188
+ # Statistics
189
+ console.print(f"\n Installed: {result.installed_count}")
190
+ if result.skipped_count > 0:
191
+ console.print(f" Skipped: {result.skipped_count}")
192
+ if result.failed_count > 0:
193
+ console.print(f" Failed: {result.failed_count}")
194
+
195
+ else:
196
+ # Failure message
197
+ console.print(f"\n[red]✗ Installation failed for {result.package_name}[/red]")
198
+ if result.error_message:
199
+ console.print(f"[red] Error: {result.error_message}[/red]")
200
+
201
+
202
+ @package_app.command(name="list")
203
+ def list_packages_command(
204
+ project: Optional[str] = typer.Option(
205
+ None,
206
+ "--project",
207
+ "-p",
208
+ help="Project root directory (defaults to current directory)",
209
+ ),
210
+ json_output: bool = typer.Option(
211
+ False,
212
+ "--json",
213
+ help="Output results as JSON",
214
+ ),
215
+ ) -> None:
216
+ """
217
+ List installed packages in a project.
218
+
219
+ Example:
220
+ aiconfig package list
221
+ aiconfig package list --project ~/my-project
222
+ """
223
+ try:
224
+ # Determine project root
225
+ if project:
226
+ project_root = Path(project).resolve()
227
+ if not project_root.exists():
228
+ console.print(f"[red]Error: Project directory not found: {project}[/red]")
229
+ raise typer.Exit(1)
230
+ else:
231
+ project_root_maybe = find_project_root()
232
+ if not project_root_maybe:
233
+ console.print("[red]Error: Could not find project root. " "Use --project to specify explicitly.[/red]")
234
+ raise typer.Exit(1)
235
+ project_root = project_root_maybe
236
+
237
+ # Get tracker
238
+ tracker_file = project_root / ".ai-config-kit" / "packages.json"
239
+ tracker = PackageTracker(tracker_file)
240
+
241
+ # Get installed packages
242
+ packages = tracker.get_installed_packages()
243
+
244
+ if json_output:
245
+ import json
246
+
247
+ output = []
248
+ for pkg in packages:
249
+ output.append(
250
+ {
251
+ "name": pkg.package_name,
252
+ "namespace": pkg.namespace,
253
+ "version": pkg.version,
254
+ "status": pkg.status.value,
255
+ "scope": pkg.scope.value,
256
+ "installed_at": pkg.installed_at.isoformat(),
257
+ "updated_at": pkg.updated_at.isoformat(),
258
+ "component_count": len(pkg.components),
259
+ }
260
+ )
261
+ console.print(json.dumps(output, indent=2))
262
+ else:
263
+ if not packages:
264
+ console.print("[yellow]No packages installed in this project.[/yellow]")
265
+ return
266
+
267
+ console.print(f"\n[cyan]Installed packages in {project_root}:[/cyan]\n")
268
+
269
+ table = Table(show_header=True, header_style="bold cyan")
270
+ table.add_column("Package", style="green")
271
+ table.add_column("Version", style="blue")
272
+ table.add_column("Status", style="yellow")
273
+ table.add_column("Components", justify="right", style="magenta")
274
+ table.add_column("Installed", style="dim")
275
+
276
+ for pkg in packages:
277
+ status_icon = "✓" if pkg.status == InstallationStatus.COMPLETE else "⚠"
278
+ table.add_row(
279
+ f"{pkg.namespace}/{pkg.package_name}",
280
+ pkg.version,
281
+ f"{status_icon} {pkg.status.value}",
282
+ str(len(pkg.components)),
283
+ pkg.installed_at.strftime("%Y-%m-%d %H:%M"),
284
+ )
285
+
286
+ console.print(table)
287
+ console.print(f"\n[dim]Total: {len(packages)} package(s)[/dim]\n")
288
+
289
+ except Exception as e:
290
+ console.print(f"[red]Failed to list packages: {e}[/red]")
291
+ raise typer.Exit(1)
292
+
293
+
294
+ @package_app.command(name="uninstall")
295
+ def uninstall_package_command(
296
+ package_name: str = typer.Argument(
297
+ ...,
298
+ help="Package name to uninstall",
299
+ ),
300
+ project: Optional[str] = typer.Option(
301
+ None,
302
+ "--project",
303
+ "-p",
304
+ help="Project root directory (defaults to current directory)",
305
+ ),
306
+ yes: bool = typer.Option(
307
+ False,
308
+ "--yes",
309
+ "-y",
310
+ help="Skip confirmation prompt",
311
+ ),
312
+ ) -> None:
313
+ """
314
+ Uninstall a package from a project.
315
+
316
+ This removes the package's files and tracking record.
317
+
318
+ Example:
319
+ aiconfig package uninstall test-package
320
+ aiconfig package uninstall my-org/my-package --yes
321
+ """
322
+ try:
323
+ # Determine project root
324
+ if project:
325
+ project_root = Path(project).resolve()
326
+ if not project_root.exists():
327
+ console.print(f"[red]Error: Project directory not found: {project}[/red]")
328
+ raise typer.Exit(1)
329
+ else:
330
+ project_root_maybe = find_project_root()
331
+ if not project_root_maybe:
332
+ console.print("[red]Error: Could not find project root. " "Use --project to specify explicitly.[/red]")
333
+ raise typer.Exit(1)
334
+ project_root = project_root_maybe
335
+
336
+ # Get tracker
337
+ tracker_file = project_root / ".ai-config-kit" / "packages.json"
338
+ tracker = PackageTracker(tracker_file)
339
+
340
+ # Get package
341
+ package = tracker.get_package(package_name, InstallationScope.PROJECT)
342
+ if not package:
343
+ console.print(f"[red]Error: Package '{package_name}' is not installed in this project.[/red]")
344
+ raise typer.Exit(1)
345
+
346
+ # Confirm uninstall
347
+ if not yes:
348
+ console.print("\n[yellow]Package to uninstall:[/yellow]")
349
+ console.print(f" Name: {package.package_name}")
350
+ console.print(f" Version: {package.version}")
351
+ console.print(f" Components: {len(package.components)}")
352
+
353
+ confirm = typer.confirm("\nAre you sure you want to uninstall this package?")
354
+ if not confirm:
355
+ console.print("[yellow]Uninstall cancelled.[/yellow]")
356
+ raise typer.Exit(0)
357
+
358
+ # Remove component files
359
+ removed_count = 0
360
+ failed_count = 0
361
+ for component in package.components:
362
+ try:
363
+ file_path = project_root / component.installed_path
364
+ if file_path.exists():
365
+ file_path.unlink()
366
+ removed_count += 1
367
+ console.print(f"[dim] Removed: {component.installed_path}[/dim]")
368
+ except Exception as e:
369
+ console.print(f"[yellow] Warning: Failed to remove {component.installed_path}: {e}[/yellow]")
370
+ failed_count += 1
371
+
372
+ # Remove from tracker
373
+ tracker.remove_package(package_name, InstallationScope.PROJECT)
374
+
375
+ # Summary
376
+ console.print(f"\n[green]✓ Uninstalled {package.package_name} v{package.version}[/green]")
377
+ console.print(f" Removed {removed_count} file(s)")
378
+ if failed_count > 0:
379
+ console.print(f"[yellow] Failed to remove {failed_count} file(s)[/yellow]")
380
+
381
+ except Exception as e:
382
+ console.print(f"[red]Failed to uninstall package: {e}[/red]")
383
+ raise typer.Exit(1)