fips-agents-cli 0.1.8__tar.gz → 0.2.0__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.
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/.github/workflows/test.yml +2 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/.github/workflows/workflow.yaml +1 -1
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/PKG-INFO +24 -1
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/README.md +23 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/pyproject.toml +1 -1
- fips_agents_cli-0.2.0/src/fips_agents_cli/commands/create.py +447 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/commands/model_car.py +74 -5
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/commands/patch.py +15 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/tools/git.py +60 -0
- fips_agents_cli-0.2.0/src/fips_agents_cli/tools/github.py +193 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/tools/project.py +12 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/version.py +1 -1
- fips_agents_cli-0.2.0/tests/test_create.py +559 -0
- fips_agents_cli-0.2.0/tests/test_github.py +274 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/tests/test_model_car.py +26 -8
- fips_agents_cli-0.1.8/src/fips_agents_cli/commands/create.py +0 -192
- fips_agents_cli-0.1.8/tests/test_create.py +0 -193
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/.claude/commands/create-release.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/.github/agents/README.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/.github/agents/create-release.agent.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/.gitignore +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/AGENT_FRAMEWORK_PLAN.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/BAML_RESEARCH_REPORT.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/CLAUDE.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/GENERATOR_IMPLEMENTATION_PLAN.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/IMPLEMENTATION_SUMMARY.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/Ignite-CLI-Architecture-Analysis.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/LICENSE +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/MVP-PLAN.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/PLAN.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/PROMPT_ISSUE.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/PUBLISHING.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/QUICK_START_PUBLISHING.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/RELEASE_CHECKLIST.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/scripts/README.md +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/scripts/release.sh +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/__init__.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/__main__.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/cli.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/commands/__init__.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/commands/generate.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/tools/__init__.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/tools/filesystem.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/tools/generators.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/tools/patching.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/src/fips_agents_cli/tools/validation.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/tests/__init__.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/tests/conftest.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/tests/test_filesystem.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/tests/test_generate.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/tests/test_generators.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/tests/test_project.py +0 -0
- {fips_agents_cli-0.1.8 → fips_agents_cli-0.2.0}/tests/test_validation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fips-agents-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: CLI tool for creating and managing FIPS-compliant AI agent projects
|
|
5
5
|
Project-URL: Homepage, https://github.com/rdwj/fips-agents-cli
|
|
6
6
|
Project-URL: Repository, https://github.com/rdwj/fips-agents-cli
|
|
@@ -528,6 +528,29 @@ MIT License - see LICENSE file for details
|
|
|
528
528
|
|
|
529
529
|
## Changelog
|
|
530
530
|
|
|
531
|
+
### Version 0.2.0
|
|
532
|
+
|
|
533
|
+
- Feature: GitHub integration for `create mcp-server` command
|
|
534
|
+
- Feature: New `--github` flag to create GitHub repository and push code
|
|
535
|
+
- Feature: New `--local` flag to skip GitHub and create local-only project
|
|
536
|
+
- Feature: Non-interactive mode (`--yes`) for agent/CI workflows
|
|
537
|
+
- Feature: New `--private` flag to create private GitHub repositories
|
|
538
|
+
- Feature: New `--org` option to create repositories in GitHub organizations
|
|
539
|
+
- Feature: New `--description` option for GitHub repository descriptions
|
|
540
|
+
- Feature: New `--remote-only` flag to create GitHub repo without local clone
|
|
541
|
+
- Feature: Added missing `patch build` subcommand for updating build/deployment files
|
|
542
|
+
- Feature: GitHub metadata tracking in `.template-info` file
|
|
543
|
+
- Feature: New git utilities for remote management (`add_remote`, `push_to_remote`)
|
|
544
|
+
- Improvement: Auto-detects `gh` CLI and prompts user when available
|
|
545
|
+
- Improvement: Clean git history - customizes project before initial push
|
|
546
|
+
|
|
547
|
+
### Version 0.1.9
|
|
548
|
+
|
|
549
|
+
- Feature: Added `.fips-agents-cli` directory to ModelCar projects with generation metadata
|
|
550
|
+
- Feature: ModelCar projects now include `info.json` with source, destination, and generator info
|
|
551
|
+
- Feature: ModelCar projects now include `CLAUDE.md` with project-specific Claude Code instructions
|
|
552
|
+
- Improvement: Consistent project metadata structure between MCP server and ModelCar projects
|
|
553
|
+
|
|
531
554
|
### Version 0.1.8
|
|
532
555
|
|
|
533
556
|
- Feature: Added GitHub Copilot agent template support
|
|
@@ -495,6 +495,29 @@ MIT License - see LICENSE file for details
|
|
|
495
495
|
|
|
496
496
|
## Changelog
|
|
497
497
|
|
|
498
|
+
### Version 0.2.0
|
|
499
|
+
|
|
500
|
+
- Feature: GitHub integration for `create mcp-server` command
|
|
501
|
+
- Feature: New `--github` flag to create GitHub repository and push code
|
|
502
|
+
- Feature: New `--local` flag to skip GitHub and create local-only project
|
|
503
|
+
- Feature: Non-interactive mode (`--yes`) for agent/CI workflows
|
|
504
|
+
- Feature: New `--private` flag to create private GitHub repositories
|
|
505
|
+
- Feature: New `--org` option to create repositories in GitHub organizations
|
|
506
|
+
- Feature: New `--description` option for GitHub repository descriptions
|
|
507
|
+
- Feature: New `--remote-only` flag to create GitHub repo without local clone
|
|
508
|
+
- Feature: Added missing `patch build` subcommand for updating build/deployment files
|
|
509
|
+
- Feature: GitHub metadata tracking in `.template-info` file
|
|
510
|
+
- Feature: New git utilities for remote management (`add_remote`, `push_to_remote`)
|
|
511
|
+
- Improvement: Auto-detects `gh` CLI and prompts user when available
|
|
512
|
+
- Improvement: Clean git history - customizes project before initial push
|
|
513
|
+
|
|
514
|
+
### Version 0.1.9
|
|
515
|
+
|
|
516
|
+
- Feature: Added `.fips-agents-cli` directory to ModelCar projects with generation metadata
|
|
517
|
+
- Feature: ModelCar projects now include `info.json` with source, destination, and generator info
|
|
518
|
+
- Feature: ModelCar projects now include `CLAUDE.md` with project-specific Claude Code instructions
|
|
519
|
+
- Improvement: Consistent project metadata structure between MCP server and ModelCar projects
|
|
520
|
+
|
|
498
521
|
### Version 0.1.8
|
|
499
522
|
|
|
500
523
|
- Feature: Added GitHub Copilot agent template support
|
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
"""Create command for generating new projects from templates."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
from rich.panel import Panel
|
|
8
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
9
|
+
|
|
10
|
+
from fips_agents_cli.commands.model_car import model_car
|
|
11
|
+
from fips_agents_cli.tools.filesystem import resolve_target_path, validate_target_directory
|
|
12
|
+
from fips_agents_cli.tools.git import (
|
|
13
|
+
add_remote,
|
|
14
|
+
clone_template,
|
|
15
|
+
init_repository,
|
|
16
|
+
is_git_installed,
|
|
17
|
+
push_to_remote,
|
|
18
|
+
)
|
|
19
|
+
from fips_agents_cli.tools.github import (
|
|
20
|
+
check_gh_prerequisites,
|
|
21
|
+
create_github_repo,
|
|
22
|
+
get_github_username,
|
|
23
|
+
is_gh_authenticated,
|
|
24
|
+
is_gh_installed,
|
|
25
|
+
)
|
|
26
|
+
from fips_agents_cli.tools.project import (
|
|
27
|
+
cleanup_template_files,
|
|
28
|
+
to_module_name,
|
|
29
|
+
update_project_name,
|
|
30
|
+
validate_project_name,
|
|
31
|
+
write_template_info,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
console = Console()
|
|
35
|
+
|
|
36
|
+
# Template URL for MCP server projects
|
|
37
|
+
MCP_SERVER_TEMPLATE_URL = "https://github.com/rdwj/mcp-server-template"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@click.group()
|
|
41
|
+
def create():
|
|
42
|
+
"""Create new projects from templates."""
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# Register subcommands
|
|
47
|
+
create.add_command(model_car)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@create.command("mcp-server")
|
|
51
|
+
@click.argument("project_name")
|
|
52
|
+
@click.option(
|
|
53
|
+
"--target-dir",
|
|
54
|
+
"-t",
|
|
55
|
+
default=None,
|
|
56
|
+
help="Target directory for the project (default: current directory)",
|
|
57
|
+
)
|
|
58
|
+
@click.option(
|
|
59
|
+
"--no-git",
|
|
60
|
+
is_flag=True,
|
|
61
|
+
default=False,
|
|
62
|
+
help="Skip git repository initialization",
|
|
63
|
+
)
|
|
64
|
+
@click.option(
|
|
65
|
+
"--github",
|
|
66
|
+
"use_github",
|
|
67
|
+
is_flag=True,
|
|
68
|
+
default=False,
|
|
69
|
+
help="Create GitHub repository and push code",
|
|
70
|
+
)
|
|
71
|
+
@click.option(
|
|
72
|
+
"--local",
|
|
73
|
+
"use_local",
|
|
74
|
+
is_flag=True,
|
|
75
|
+
default=False,
|
|
76
|
+
help="Create local project only (skip GitHub)",
|
|
77
|
+
)
|
|
78
|
+
@click.option(
|
|
79
|
+
"--yes",
|
|
80
|
+
"-y",
|
|
81
|
+
is_flag=True,
|
|
82
|
+
default=False,
|
|
83
|
+
help="Non-interactive mode (use defaults, skip prompts)",
|
|
84
|
+
)
|
|
85
|
+
@click.option(
|
|
86
|
+
"--private",
|
|
87
|
+
is_flag=True,
|
|
88
|
+
default=False,
|
|
89
|
+
help="Make GitHub repository private (default: public)",
|
|
90
|
+
)
|
|
91
|
+
@click.option(
|
|
92
|
+
"--org",
|
|
93
|
+
default=None,
|
|
94
|
+
help="GitHub organization to create repository in",
|
|
95
|
+
)
|
|
96
|
+
@click.option(
|
|
97
|
+
"--description",
|
|
98
|
+
"-d",
|
|
99
|
+
"repo_description",
|
|
100
|
+
default=None,
|
|
101
|
+
help="GitHub repository description",
|
|
102
|
+
)
|
|
103
|
+
@click.option(
|
|
104
|
+
"--remote-only",
|
|
105
|
+
is_flag=True,
|
|
106
|
+
default=False,
|
|
107
|
+
help="Create GitHub repo only, don't clone locally",
|
|
108
|
+
)
|
|
109
|
+
def mcp_server(
|
|
110
|
+
project_name: str,
|
|
111
|
+
target_dir: str | None,
|
|
112
|
+
no_git: bool,
|
|
113
|
+
use_github: bool,
|
|
114
|
+
use_local: bool,
|
|
115
|
+
yes: bool,
|
|
116
|
+
private: bool,
|
|
117
|
+
org: str | None,
|
|
118
|
+
repo_description: str | None,
|
|
119
|
+
remote_only: bool,
|
|
120
|
+
):
|
|
121
|
+
"""
|
|
122
|
+
Create a new MCP server project from template.
|
|
123
|
+
|
|
124
|
+
PROJECT_NAME must start with a lowercase letter and contain only
|
|
125
|
+
lowercase letters, numbers, hyphens, and underscores.
|
|
126
|
+
|
|
127
|
+
By default, if GitHub CLI (gh) is installed and authenticated, prompts
|
|
128
|
+
to create a GitHub repository. Use --local to skip this, or --github
|
|
129
|
+
to require it. Use --yes for non-interactive mode (agents/CI).
|
|
130
|
+
|
|
131
|
+
Examples:
|
|
132
|
+
|
|
133
|
+
fips-agents create mcp-server my-mcp-server
|
|
134
|
+
|
|
135
|
+
fips-agents create mcp-server my-mcp-server --github --private
|
|
136
|
+
|
|
137
|
+
fips-agents create mcp-server my-mcp-server --local
|
|
138
|
+
|
|
139
|
+
fips-agents create mcp-server my-mcp-server --yes # Non-interactive
|
|
140
|
+
"""
|
|
141
|
+
try:
|
|
142
|
+
# Step 1: Validate options
|
|
143
|
+
if use_github and use_local:
|
|
144
|
+
console.print("[red]✗[/red] Cannot use --github and --local together")
|
|
145
|
+
sys.exit(1)
|
|
146
|
+
|
|
147
|
+
if remote_only and use_local:
|
|
148
|
+
console.print("[red]✗[/red] Cannot use --remote-only with --local")
|
|
149
|
+
sys.exit(1)
|
|
150
|
+
|
|
151
|
+
# Step 2: Validate project name
|
|
152
|
+
console.print("\n[bold cyan]Creating MCP Server Project[/bold cyan]\n")
|
|
153
|
+
|
|
154
|
+
is_valid, error_msg = validate_project_name(project_name)
|
|
155
|
+
if not is_valid:
|
|
156
|
+
console.print(f"[red]✗[/red] Invalid project name: {error_msg}")
|
|
157
|
+
sys.exit(1)
|
|
158
|
+
|
|
159
|
+
console.print(f"[green]✓[/green] Project name '{project_name}' is valid")
|
|
160
|
+
|
|
161
|
+
# Step 3: Determine mode (GitHub or local)
|
|
162
|
+
create_github = _determine_github_mode(use_github, use_local, yes)
|
|
163
|
+
|
|
164
|
+
# Step 4: Check prerequisites
|
|
165
|
+
if not is_git_installed():
|
|
166
|
+
console.print(
|
|
167
|
+
"[yellow]⚠[/yellow] Git is not installed. This is required for cloning templates."
|
|
168
|
+
)
|
|
169
|
+
console.print("[yellow]Hint:[/yellow] Install git from https://git-scm.com/downloads")
|
|
170
|
+
sys.exit(1)
|
|
171
|
+
|
|
172
|
+
if create_github:
|
|
173
|
+
ready, error_msg = check_gh_prerequisites()
|
|
174
|
+
if not ready:
|
|
175
|
+
console.print(f"[red]✗[/red] {error_msg}")
|
|
176
|
+
sys.exit(1)
|
|
177
|
+
|
|
178
|
+
# Step 5: Resolve and validate target directory (skip for remote-only)
|
|
179
|
+
target_path = None
|
|
180
|
+
if not remote_only:
|
|
181
|
+
target_path = resolve_target_path(project_name, target_dir)
|
|
182
|
+
|
|
183
|
+
is_valid, error_msg = validate_target_directory(target_path, allow_existing=False)
|
|
184
|
+
if not is_valid:
|
|
185
|
+
console.print(f"[red]✗[/red] {error_msg}")
|
|
186
|
+
console.print(
|
|
187
|
+
"\n[yellow]Hint:[/yellow] Choose a different name or remove the existing "
|
|
188
|
+
"directory"
|
|
189
|
+
)
|
|
190
|
+
sys.exit(1)
|
|
191
|
+
|
|
192
|
+
console.print(f"[green]✓[/green] Target directory: {target_path}")
|
|
193
|
+
|
|
194
|
+
# Step 6: Create GitHub repo first (if GitHub mode)
|
|
195
|
+
github_repo = None
|
|
196
|
+
github_url = None
|
|
197
|
+
if create_github:
|
|
198
|
+
success, github_url, error_msg = create_github_repo(
|
|
199
|
+
name=project_name,
|
|
200
|
+
private=private,
|
|
201
|
+
org=org,
|
|
202
|
+
description=repo_description,
|
|
203
|
+
)
|
|
204
|
+
if not success:
|
|
205
|
+
console.print(f"[red]✗[/red] {error_msg}")
|
|
206
|
+
sys.exit(1)
|
|
207
|
+
|
|
208
|
+
# Construct repo identifier
|
|
209
|
+
owner = org if org else get_github_username()
|
|
210
|
+
github_repo = f"{owner}/{project_name}"
|
|
211
|
+
|
|
212
|
+
# Step 7: Handle remote-only mode
|
|
213
|
+
if remote_only:
|
|
214
|
+
_show_remote_only_success(project_name, github_url, github_repo)
|
|
215
|
+
return
|
|
216
|
+
|
|
217
|
+
# Step 8: Clone template repository
|
|
218
|
+
template_commit = None
|
|
219
|
+
with Progress(
|
|
220
|
+
SpinnerColumn(),
|
|
221
|
+
TextColumn("[progress.description]{task.description}"),
|
|
222
|
+
console=console,
|
|
223
|
+
) as progress:
|
|
224
|
+
progress.add_task(description="Cloning template repository...", total=None)
|
|
225
|
+
try:
|
|
226
|
+
template_commit = clone_template(MCP_SERVER_TEMPLATE_URL, target_path)
|
|
227
|
+
except Exception as e:
|
|
228
|
+
console.print("\n[red]✗[/red] Failed to clone template repository")
|
|
229
|
+
console.print(f"[red]Error:[/red] {e}")
|
|
230
|
+
console.print(
|
|
231
|
+
f"\n[yellow]Hint:[/yellow] Check your internet connection and verify "
|
|
232
|
+
f"the template URL is accessible:\n{MCP_SERVER_TEMPLATE_URL}"
|
|
233
|
+
)
|
|
234
|
+
sys.exit(1)
|
|
235
|
+
|
|
236
|
+
# Step 9: Customize project
|
|
237
|
+
with Progress(
|
|
238
|
+
SpinnerColumn(),
|
|
239
|
+
TextColumn("[progress.description]{task.description}"),
|
|
240
|
+
console=console,
|
|
241
|
+
) as progress:
|
|
242
|
+
progress.add_task(description="Customizing project...", total=None)
|
|
243
|
+
try:
|
|
244
|
+
update_project_name(target_path, project_name)
|
|
245
|
+
cleanup_template_files(target_path)
|
|
246
|
+
if template_commit:
|
|
247
|
+
write_template_info(
|
|
248
|
+
target_path,
|
|
249
|
+
project_name,
|
|
250
|
+
MCP_SERVER_TEMPLATE_URL,
|
|
251
|
+
template_commit,
|
|
252
|
+
github_repo=github_repo,
|
|
253
|
+
github_url=github_url,
|
|
254
|
+
)
|
|
255
|
+
except Exception as e:
|
|
256
|
+
console.print("\n[red]✗[/red] Failed to customize project")
|
|
257
|
+
console.print(f"[red]Error:[/red] {e}")
|
|
258
|
+
sys.exit(1)
|
|
259
|
+
|
|
260
|
+
# Step 10: Initialize git repository
|
|
261
|
+
if not no_git:
|
|
262
|
+
with Progress(
|
|
263
|
+
SpinnerColumn(),
|
|
264
|
+
TextColumn("[progress.description]{task.description}"),
|
|
265
|
+
console=console,
|
|
266
|
+
) as progress:
|
|
267
|
+
progress.add_task(description="Initializing git repository...", total=None)
|
|
268
|
+
try:
|
|
269
|
+
init_repository(target_path, initial_commit=True)
|
|
270
|
+
except Exception as e:
|
|
271
|
+
console.print("\n[yellow]⚠[/yellow] Failed to initialize git repository")
|
|
272
|
+
console.print(f"[yellow]Warning:[/yellow] {e}")
|
|
273
|
+
console.print(
|
|
274
|
+
"[yellow]You can initialize git manually later with:[/yellow] git init"
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
# Step 11: Push to GitHub (if GitHub mode)
|
|
278
|
+
if create_github and not no_git:
|
|
279
|
+
try:
|
|
280
|
+
add_remote(target_path, "origin", github_url)
|
|
281
|
+
push_success = push_to_remote(target_path, "origin", "main")
|
|
282
|
+
if not push_success:
|
|
283
|
+
console.print(
|
|
284
|
+
"\n[yellow]⚠[/yellow] Failed to push to GitHub. "
|
|
285
|
+
"You can push manually with: git push -u origin main"
|
|
286
|
+
)
|
|
287
|
+
except Exception as e:
|
|
288
|
+
console.print(f"\n[yellow]⚠[/yellow] Failed to set up GitHub remote: {e}")
|
|
289
|
+
console.print("[yellow]You can add the remote manually with:[/yellow]")
|
|
290
|
+
console.print(f" git remote add origin {github_url}")
|
|
291
|
+
console.print(" git push -u origin main")
|
|
292
|
+
|
|
293
|
+
# Step 12: Success message
|
|
294
|
+
_show_success_message(
|
|
295
|
+
project_name=project_name,
|
|
296
|
+
target_path=target_path,
|
|
297
|
+
github_url=github_url,
|
|
298
|
+
github_repo=github_repo,
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
except KeyboardInterrupt:
|
|
302
|
+
console.print("\n[yellow]⚠[/yellow] Operation cancelled by user")
|
|
303
|
+
sys.exit(130)
|
|
304
|
+
except Exception as e:
|
|
305
|
+
console.print(f"\n[red]✗[/red] Unexpected error: {e}")
|
|
306
|
+
sys.exit(1)
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def _determine_github_mode(use_github: bool, use_local: bool, yes: bool) -> bool:
|
|
310
|
+
"""
|
|
311
|
+
Determine whether to create a GitHub repository.
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
use_github: --github flag was set
|
|
315
|
+
use_local: --local flag was set
|
|
316
|
+
yes: --yes flag was set (non-interactive mode)
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
bool: True if GitHub repository should be created
|
|
320
|
+
"""
|
|
321
|
+
# Explicit flags take precedence
|
|
322
|
+
if use_local:
|
|
323
|
+
console.print("[dim]Mode: Local only (--local)[/dim]")
|
|
324
|
+
return False
|
|
325
|
+
|
|
326
|
+
if use_github:
|
|
327
|
+
console.print("[dim]Mode: GitHub (--github)[/dim]")
|
|
328
|
+
return True
|
|
329
|
+
|
|
330
|
+
# Check if gh is available
|
|
331
|
+
if not is_gh_installed():
|
|
332
|
+
console.print("[dim]Mode: Local only (GitHub CLI not installed)[/dim]")
|
|
333
|
+
return False
|
|
334
|
+
|
|
335
|
+
if not is_gh_authenticated():
|
|
336
|
+
console.print("[dim]Mode: Local only (GitHub CLI not authenticated)[/dim]")
|
|
337
|
+
return False
|
|
338
|
+
|
|
339
|
+
# gh is available - decide based on interactive mode
|
|
340
|
+
if yes:
|
|
341
|
+
# Non-interactive: default to GitHub
|
|
342
|
+
console.print("[dim]Mode: GitHub (--yes with gh available)[/dim]")
|
|
343
|
+
return True
|
|
344
|
+
|
|
345
|
+
# Interactive: prompt user
|
|
346
|
+
console.print("[cyan]GitHub CLI detected and authenticated.[/cyan]")
|
|
347
|
+
return click.confirm("Create GitHub repository?", default=True)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def _show_success_message(
|
|
351
|
+
project_name: str,
|
|
352
|
+
target_path,
|
|
353
|
+
github_url: str | None,
|
|
354
|
+
github_repo: str | None,
|
|
355
|
+
) -> None:
|
|
356
|
+
"""Display success message with next steps."""
|
|
357
|
+
module_name = to_module_name(project_name)
|
|
358
|
+
|
|
359
|
+
# Build project details section
|
|
360
|
+
details = f""" • Name: {project_name}
|
|
361
|
+
• Module: {module_name}
|
|
362
|
+
• Location: {target_path}"""
|
|
363
|
+
|
|
364
|
+
if github_url:
|
|
365
|
+
details += f"\n • GitHub: {github_url}"
|
|
366
|
+
|
|
367
|
+
# Build next steps based on mode
|
|
368
|
+
if github_url:
|
|
369
|
+
next_steps = f"""
|
|
370
|
+
1. Navigate to your project:
|
|
371
|
+
[dim]cd {target_path.name}[/dim]
|
|
372
|
+
|
|
373
|
+
2. Create and activate a virtual environment:
|
|
374
|
+
[dim]python -m venv venv[/dim]
|
|
375
|
+
[dim]source venv/bin/activate[/dim] # On Windows: venv\\Scripts\\activate
|
|
376
|
+
|
|
377
|
+
3. Install the project in editable mode:
|
|
378
|
+
[dim]pip install -e .[dev][/dim]
|
|
379
|
+
|
|
380
|
+
4. Start developing your MCP server!
|
|
381
|
+
[dim]Your code is already pushed to GitHub[/dim]
|
|
382
|
+
|
|
383
|
+
5. Run tests:
|
|
384
|
+
[dim]pytest[/dim]"""
|
|
385
|
+
else:
|
|
386
|
+
next_steps = f"""
|
|
387
|
+
1. Navigate to your project:
|
|
388
|
+
[dim]cd {target_path.name}[/dim]
|
|
389
|
+
|
|
390
|
+
2. Create and activate a virtual environment:
|
|
391
|
+
[dim]python -m venv venv[/dim]
|
|
392
|
+
[dim]source venv/bin/activate[/dim] # On Windows: venv\\Scripts\\activate
|
|
393
|
+
|
|
394
|
+
3. Install the project in editable mode:
|
|
395
|
+
[dim]pip install -e .[dev][/dim]
|
|
396
|
+
|
|
397
|
+
4. Start developing your MCP server!
|
|
398
|
+
[dim]Edit src/ files to add your functionality[/dim]
|
|
399
|
+
|
|
400
|
+
5. Run tests:
|
|
401
|
+
[dim]pytest[/dim]"""
|
|
402
|
+
|
|
403
|
+
success_message = f"""
|
|
404
|
+
[bold green]✓ Successfully created MCP server project![/bold green]
|
|
405
|
+
|
|
406
|
+
[bold cyan]Project Details:[/bold cyan]
|
|
407
|
+
{details}
|
|
408
|
+
|
|
409
|
+
[bold cyan]Next Steps:[/bold cyan]
|
|
410
|
+
{next_steps}
|
|
411
|
+
|
|
412
|
+
[bold cyan]Documentation:[/bold cyan]
|
|
413
|
+
• Check the README.md in your project for detailed instructions
|
|
414
|
+
• MCP Protocol docs: https://modelcontextprotocol.io/
|
|
415
|
+
"""
|
|
416
|
+
|
|
417
|
+
console.print(Panel(success_message, border_style="green", padding=(1, 2)))
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
def _show_remote_only_success(
|
|
421
|
+
project_name: str,
|
|
422
|
+
github_url: str,
|
|
423
|
+
github_repo: str,
|
|
424
|
+
) -> None:
|
|
425
|
+
"""Display success message for remote-only mode."""
|
|
426
|
+
success_message = f"""
|
|
427
|
+
[bold green]✓ Successfully created GitHub repository![/bold green]
|
|
428
|
+
|
|
429
|
+
[bold cyan]Repository Details:[/bold cyan]
|
|
430
|
+
• Name: {project_name}
|
|
431
|
+
• GitHub: {github_url}
|
|
432
|
+
|
|
433
|
+
[bold cyan]Next Steps:[/bold cyan]
|
|
434
|
+
|
|
435
|
+
1. Clone the repository:
|
|
436
|
+
[dim]git clone {github_url}[/dim]
|
|
437
|
+
[dim]cd {project_name}[/dim]
|
|
438
|
+
|
|
439
|
+
2. The repository contains the MCP server template.
|
|
440
|
+
Customize it for your project.
|
|
441
|
+
|
|
442
|
+
[bold cyan]Note:[/bold cyan]
|
|
443
|
+
The repository contains the raw template.
|
|
444
|
+
You may want to customize project names and paths.
|
|
445
|
+
"""
|
|
446
|
+
|
|
447
|
+
console.print(Panel(success_message, border_style="green", padding=(1, 2)))
|
|
@@ -536,22 +536,85 @@ serving.knative.dev/progress-deadline: 30m
|
|
|
536
536
|
"""
|
|
537
537
|
|
|
538
538
|
|
|
539
|
+
def generate_modelcar_claude_md(hf_repo_id: str, model_name: str, quay_uri: str) -> str:
|
|
540
|
+
"""Generate CLAUDE.md content for ModelCar projects."""
|
|
541
|
+
return f"""# CLAUDE.md - ModelCar Project
|
|
542
|
+
|
|
543
|
+
This file provides guidance to Claude Code when working with this ModelCar project.
|
|
544
|
+
|
|
545
|
+
## Project Overview
|
|
546
|
+
|
|
547
|
+
This is a **ModelCar** project for packaging the **{model_name}** model from HuggingFace
|
|
548
|
+
into a container image for deployment on OpenShift AI.
|
|
549
|
+
|
|
550
|
+
## Source Information
|
|
551
|
+
|
|
552
|
+
- **HuggingFace Repository:** [{hf_repo_id}](https://huggingface.co/{hf_repo_id})
|
|
553
|
+
- **Container Registry:** `{quay_uri}`
|
|
554
|
+
|
|
555
|
+
## Important Notes
|
|
556
|
+
|
|
557
|
+
1. **This is a temporary workspace** - do NOT commit model files to git
|
|
558
|
+
2. **Source of truth:** The HuggingFace repository
|
|
559
|
+
3. **Delete after use:** This directory should be deleted after pushing to registry
|
|
560
|
+
|
|
561
|
+
## Workflow
|
|
562
|
+
|
|
563
|
+
1. **Download:** `./download.sh` - Downloads model from HuggingFace
|
|
564
|
+
2. **Build & Push:** `./build-and-push.sh` - Creates and pushes container image
|
|
565
|
+
3. **Cleanup:** Delete this directory after successful push
|
|
566
|
+
|
|
567
|
+
## Files
|
|
568
|
+
|
|
569
|
+
| File | Purpose |
|
|
570
|
+
|------|---------|
|
|
571
|
+
| `download.sh` | Downloads model from HuggingFace |
|
|
572
|
+
| `build-and-push.sh` | Builds container and pushes to registry |
|
|
573
|
+
| `cleanup.sh` | Deletes local model files |
|
|
574
|
+
| `cleanup-old-images.sh` | Removes old ModelCar images from Podman |
|
|
575
|
+
| `Containerfile` | Container build instructions |
|
|
576
|
+
|
|
577
|
+
## OpenShift AI Deployment
|
|
578
|
+
|
|
579
|
+
Deploy using:
|
|
580
|
+
- **Runtime:** vLLM ServingRuntime
|
|
581
|
+
- **Source type:** OCI - v1
|
|
582
|
+
- **URI:** `oci://{quay_uri}`
|
|
583
|
+
|
|
584
|
+
## Generation Info
|
|
585
|
+
|
|
586
|
+
This project was generated using `fips-agents create model-car`.
|
|
587
|
+
See `.fips-agents-cli/info.json` for full generation metadata.
|
|
588
|
+
"""
|
|
589
|
+
|
|
590
|
+
|
|
539
591
|
def write_modelcar_info(
|
|
540
592
|
project_path,
|
|
541
593
|
hf_repo_id: str,
|
|
542
594
|
quay_uri: str,
|
|
543
595
|
project_name: str,
|
|
596
|
+
model_name: str,
|
|
544
597
|
) -> None:
|
|
545
598
|
"""
|
|
546
|
-
Write ModelCar generation metadata to .
|
|
599
|
+
Write ModelCar generation metadata to .fips-agents-cli directory.
|
|
600
|
+
|
|
601
|
+
Creates:
|
|
602
|
+
- .fips-agents-cli/info.json - Generation metadata
|
|
603
|
+
- .fips-agents-cli/CLAUDE.md - Claude Code instructions
|
|
547
604
|
|
|
548
605
|
Args:
|
|
549
606
|
project_path: Path to the project root directory
|
|
550
607
|
hf_repo_id: HuggingFace repository ID (e.g., openai/gpt-oss-20b)
|
|
551
608
|
quay_uri: Full Quay container registry URI with tag
|
|
552
609
|
project_name: Name of the generated project directory
|
|
610
|
+
model_name: Display name of the model
|
|
553
611
|
"""
|
|
554
612
|
try:
|
|
613
|
+
# Create .fips-agents-cli directory
|
|
614
|
+
fips_dir = project_path / ".fips-agents-cli"
|
|
615
|
+
fips_dir.mkdir(parents=True, exist_ok=True)
|
|
616
|
+
|
|
617
|
+
# Write info.json
|
|
555
618
|
modelcar_info = {
|
|
556
619
|
"generator": {
|
|
557
620
|
"tool": "fips-agents-cli",
|
|
@@ -574,12 +637,18 @@ def write_modelcar_info(
|
|
|
574
637
|
},
|
|
575
638
|
}
|
|
576
639
|
|
|
577
|
-
info_file =
|
|
640
|
+
info_file = fips_dir / "info.json"
|
|
578
641
|
with open(info_file, "w") as f:
|
|
579
642
|
json.dump(modelcar_info, f, indent=2)
|
|
580
643
|
f.write("\n") # Add trailing newline
|
|
581
644
|
|
|
582
|
-
|
|
645
|
+
# Write CLAUDE.md
|
|
646
|
+
claude_md_file = fips_dir / "CLAUDE.md"
|
|
647
|
+
claude_md_content = generate_modelcar_claude_md(hf_repo_id, model_name, quay_uri)
|
|
648
|
+
with open(claude_md_file, "w") as f:
|
|
649
|
+
f.write(claude_md_content)
|
|
650
|
+
|
|
651
|
+
console.print("[green]✓[/green] Created .fips-agents-cli/ with project metadata")
|
|
583
652
|
|
|
584
653
|
except Exception as e:
|
|
585
654
|
# Don't fail the entire operation if this fails
|
|
@@ -713,8 +782,8 @@ print("Next step: Run ./build-and-push.sh to build and push the container")
|
|
|
713
782
|
|
|
714
783
|
console.print(f" [green]✓[/green] Created {filename}")
|
|
715
784
|
|
|
716
|
-
# Write project metadata
|
|
717
|
-
write_modelcar_info(target_path, hf_repo_id, quay_uri, project_name)
|
|
785
|
+
# Write project metadata to .fips-agents-cli directory
|
|
786
|
+
write_modelcar_info(target_path, hf_repo_id, quay_uri, project_name, model_name)
|
|
718
787
|
|
|
719
788
|
# Step 8: Success message with instructions
|
|
720
789
|
success_message = f"""
|
|
@@ -119,6 +119,21 @@ def docs(dry_run: bool):
|
|
|
119
119
|
_patch_category("docs", dry_run)
|
|
120
120
|
|
|
121
121
|
|
|
122
|
+
@patch.command("build")
|
|
123
|
+
@click.option(
|
|
124
|
+
"--dry-run",
|
|
125
|
+
is_flag=True,
|
|
126
|
+
help="Show what would be updated without making changes",
|
|
127
|
+
)
|
|
128
|
+
def build(dry_run: bool):
|
|
129
|
+
"""
|
|
130
|
+
Update build and deployment files (Makefile, Containerfile, etc).
|
|
131
|
+
|
|
132
|
+
Shows diffs and asks for confirmation before applying changes.
|
|
133
|
+
"""
|
|
134
|
+
_patch_category("build", dry_run)
|
|
135
|
+
|
|
136
|
+
|
|
122
137
|
@patch.command("all")
|
|
123
138
|
@click.option(
|
|
124
139
|
"--dry-run",
|