supervaizer 0.10.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.
- supervaizer/__init__.py +97 -0
- supervaizer/__version__.py +10 -0
- supervaizer/account.py +308 -0
- supervaizer/account_service.py +93 -0
- supervaizer/admin/routes.py +1293 -0
- supervaizer/admin/static/js/job-start-form.js +373 -0
- supervaizer/admin/templates/agent_detail.html +145 -0
- supervaizer/admin/templates/agents.html +249 -0
- supervaizer/admin/templates/agents_grid.html +82 -0
- supervaizer/admin/templates/base.html +233 -0
- supervaizer/admin/templates/case_detail.html +230 -0
- supervaizer/admin/templates/cases_list.html +182 -0
- supervaizer/admin/templates/cases_table.html +134 -0
- supervaizer/admin/templates/console.html +389 -0
- supervaizer/admin/templates/dashboard.html +153 -0
- supervaizer/admin/templates/job_detail.html +192 -0
- supervaizer/admin/templates/job_start_test.html +109 -0
- supervaizer/admin/templates/jobs_list.html +180 -0
- supervaizer/admin/templates/jobs_table.html +122 -0
- supervaizer/admin/templates/navigation.html +163 -0
- supervaizer/admin/templates/recent_activity.html +81 -0
- supervaizer/admin/templates/server.html +105 -0
- supervaizer/admin/templates/server_status_cards.html +121 -0
- supervaizer/admin/templates/supervaize_instructions.html +212 -0
- supervaizer/agent.py +956 -0
- supervaizer/case.py +432 -0
- supervaizer/cli.py +395 -0
- supervaizer/common.py +324 -0
- supervaizer/deploy/__init__.py +16 -0
- supervaizer/deploy/cli.py +305 -0
- supervaizer/deploy/commands/__init__.py +9 -0
- supervaizer/deploy/commands/clean.py +294 -0
- supervaizer/deploy/commands/down.py +119 -0
- supervaizer/deploy/commands/local.py +460 -0
- supervaizer/deploy/commands/plan.py +167 -0
- supervaizer/deploy/commands/status.py +169 -0
- supervaizer/deploy/commands/up.py +281 -0
- supervaizer/deploy/docker.py +377 -0
- supervaizer/deploy/driver_factory.py +42 -0
- supervaizer/deploy/drivers/__init__.py +39 -0
- supervaizer/deploy/drivers/aws_app_runner.py +607 -0
- supervaizer/deploy/drivers/base.py +196 -0
- supervaizer/deploy/drivers/cloud_run.py +570 -0
- supervaizer/deploy/drivers/do_app_platform.py +504 -0
- supervaizer/deploy/health.py +404 -0
- supervaizer/deploy/state.py +210 -0
- supervaizer/deploy/templates/Dockerfile.template +44 -0
- supervaizer/deploy/templates/debug_env.py +69 -0
- supervaizer/deploy/templates/docker-compose.yml.template +37 -0
- supervaizer/deploy/templates/dockerignore.template +66 -0
- supervaizer/deploy/templates/entrypoint.sh +20 -0
- supervaizer/deploy/utils.py +52 -0
- supervaizer/event.py +181 -0
- supervaizer/examples/controller_template.py +196 -0
- supervaizer/instructions.py +145 -0
- supervaizer/job.py +392 -0
- supervaizer/job_service.py +156 -0
- supervaizer/lifecycle.py +417 -0
- supervaizer/parameter.py +233 -0
- supervaizer/protocol/__init__.py +11 -0
- supervaizer/protocol/a2a/__init__.py +21 -0
- supervaizer/protocol/a2a/model.py +227 -0
- supervaizer/protocol/a2a/routes.py +99 -0
- supervaizer/py.typed +1 -0
- supervaizer/routes.py +917 -0
- supervaizer/server.py +553 -0
- supervaizer/server_utils.py +54 -0
- supervaizer/storage.py +462 -0
- supervaizer/telemetry.py +81 -0
- supervaizer/utils/__init__.py +16 -0
- supervaizer/utils/version_check.py +56 -0
- supervaizer-0.10.5.dist-info/METADATA +317 -0
- supervaizer-0.10.5.dist-info/RECORD +76 -0
- supervaizer-0.10.5.dist-info/WHEEL +4 -0
- supervaizer-0.10.5.dist-info/entry_points.txt +2 -0
- supervaizer-0.10.5.dist-info/licenses/LICENSE.md +346 -0
supervaizer/cli.py
ADDED
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
# Copyright (c) 2024-2025 Alain Prasquier - Supervaize.com. All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
|
+
# If a copy of the MPL was not distributed with this file, you can obtain one at
|
|
5
|
+
# https://mozilla.org/MPL/2.0/.
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import os
|
|
9
|
+
import shutil
|
|
10
|
+
import signal
|
|
11
|
+
import subprocess
|
|
12
|
+
import sys
|
|
13
|
+
from typing import Any
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Optional
|
|
16
|
+
from supervaizer.deploy.cli import deploy_app
|
|
17
|
+
|
|
18
|
+
import typer
|
|
19
|
+
from rich.console import Console
|
|
20
|
+
from rich.prompt import Confirm
|
|
21
|
+
|
|
22
|
+
from supervaizer.__version__ import VERSION
|
|
23
|
+
from supervaizer.utils.version_check import check_is_latest_version
|
|
24
|
+
|
|
25
|
+
console = Console()
|
|
26
|
+
|
|
27
|
+
# Cache version status to avoid multiple checks
|
|
28
|
+
_version_status: tuple[bool, str | None] | None = None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _check_version() -> tuple[bool, str | None]:
|
|
32
|
+
"""Check version status, caching the result."""
|
|
33
|
+
global _version_status
|
|
34
|
+
if _version_status is None:
|
|
35
|
+
try:
|
|
36
|
+
_version_status = asyncio.run(check_is_latest_version())
|
|
37
|
+
except Exception:
|
|
38
|
+
# On error, assume we're on latest to avoid false positives
|
|
39
|
+
_version_status = (True, None)
|
|
40
|
+
return _version_status
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _display_version_info() -> None:
|
|
44
|
+
"""Display version information."""
|
|
45
|
+
is_latest, latest_version = _check_version()
|
|
46
|
+
console.print(f"Supervaizer v{VERSION}")
|
|
47
|
+
if latest_version:
|
|
48
|
+
if is_latest:
|
|
49
|
+
console.print(f"[green]✓[/] Up to date (latest: v{latest_version})")
|
|
50
|
+
else:
|
|
51
|
+
console.print(f"[yellow]⚠[/] Latest available: v{latest_version}")
|
|
52
|
+
console.print("Update with: [bold]pip install --upgrade supervaizer[/]")
|
|
53
|
+
else:
|
|
54
|
+
console.print("(Unable to check for latest version)")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _display_update_warning() -> None:
|
|
58
|
+
"""Display update warning for commands."""
|
|
59
|
+
is_latest, latest_version = _check_version()
|
|
60
|
+
if latest_version and not is_latest:
|
|
61
|
+
console.print(
|
|
62
|
+
f"\n[bold yellow]⚠ Warning:[/] You are running Supervaizer v{VERSION}, "
|
|
63
|
+
f"but v{latest_version} is available.\n"
|
|
64
|
+
f"Update with: [bold]pip install --upgrade supervaizer[/]\n",
|
|
65
|
+
style="yellow",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
app = typer.Typer(
|
|
70
|
+
help=f"Supervaizer Controller CLI v{VERSION} - Documentation @ https://doc.supervaize.com/docs/category/supervaizer-controller"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@app.callback(invoke_without_command=True)
|
|
75
|
+
def main_callback(
|
|
76
|
+
ctx: typer.Context,
|
|
77
|
+
version: bool = typer.Option(
|
|
78
|
+
False, "--version", "-v", help="Show version information and exit"
|
|
79
|
+
),
|
|
80
|
+
) -> None:
|
|
81
|
+
"""CLI callback that runs before any command."""
|
|
82
|
+
# Handle --version option
|
|
83
|
+
if version:
|
|
84
|
+
_display_version_info()
|
|
85
|
+
raise typer.Exit()
|
|
86
|
+
|
|
87
|
+
# Show version status in help or as warning for commands
|
|
88
|
+
if ctx.invoked_subcommand is None:
|
|
89
|
+
# For help display, show version status
|
|
90
|
+
_display_version_info()
|
|
91
|
+
else:
|
|
92
|
+
# For actual commands, show warning if not latest
|
|
93
|
+
_display_update_warning()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# Add deploy subcommand
|
|
97
|
+
app.add_typer(
|
|
98
|
+
deploy_app,
|
|
99
|
+
name="deploy",
|
|
100
|
+
help="Deploy Supervaizer agents to cloud platforms (requires deploy extras: pip install supervaizer[deploy])",
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# Create scaffold subcommand group
|
|
104
|
+
scaffold_app = typer.Typer(help="Scaffold commands for creating project files")
|
|
105
|
+
app.add_typer(scaffold_app, name="scaffold", invoke_without_command=True)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@app.command()
|
|
109
|
+
def start(
|
|
110
|
+
public_url: Optional[str] = typer.Option(
|
|
111
|
+
os.environ.get("SUPERVAIZER_PUBLIC_URL") or None,
|
|
112
|
+
help="Public URL to use for inbound connections",
|
|
113
|
+
),
|
|
114
|
+
host: str = typer.Option(
|
|
115
|
+
os.environ.get("SUPERVAIZER_HOST", "0.0.0.0"), help="Host to bind the server to"
|
|
116
|
+
),
|
|
117
|
+
port: int = typer.Option(
|
|
118
|
+
int(os.environ.get("SUPERVAIZER_PORT") or "8000"),
|
|
119
|
+
help="Port to bind the server to",
|
|
120
|
+
),
|
|
121
|
+
log_level: str = typer.Option(
|
|
122
|
+
os.environ.get("SUPERVAIZER_LOG_LEVEL", "INFO"),
|
|
123
|
+
help="Log level (DEBUG, INFO, WARNING, ERROR)",
|
|
124
|
+
),
|
|
125
|
+
debug: bool = typer.Option(
|
|
126
|
+
(os.environ.get("SUPERVAIZER_DEBUG") or "False").lower() == "true",
|
|
127
|
+
help="Enable debug mode",
|
|
128
|
+
),
|
|
129
|
+
reload: bool = typer.Option(
|
|
130
|
+
(os.environ.get("SUPERVAIZER_RELOAD") or "False").lower() == "true",
|
|
131
|
+
help="Enable auto-reload",
|
|
132
|
+
),
|
|
133
|
+
environment: str = typer.Option(
|
|
134
|
+
os.environ.get("SUPERVAIZER_ENVIRONMENT", "dev"), help="Environment name"
|
|
135
|
+
),
|
|
136
|
+
persist: bool = typer.Option(
|
|
137
|
+
(os.environ.get("SUPERVAIZER_PERSISTENCE") or "false").lower()
|
|
138
|
+
in ("true", "1", "yes"),
|
|
139
|
+
"--persist/--no-persist",
|
|
140
|
+
help="Persist data to file (default: off; set for self-hosted, off for Vercel/serverless)",
|
|
141
|
+
),
|
|
142
|
+
script_path: Optional[str] = typer.Argument(
|
|
143
|
+
None,
|
|
144
|
+
help="Path to the supervaizer_control.py script",
|
|
145
|
+
),
|
|
146
|
+
) -> None:
|
|
147
|
+
"""Start the Supervaizer Controller server."""
|
|
148
|
+
if script_path is None:
|
|
149
|
+
# Try to get from environment variable first, then default
|
|
150
|
+
script_path = (
|
|
151
|
+
os.environ.get("SUPERVAIZER_SCRIPT_PATH") or "supervaizer_control.py"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
if not os.path.exists(script_path):
|
|
155
|
+
console.print(f"[bold red]Error:[/] {script_path} not found")
|
|
156
|
+
console.print("Run [bold]supervaizer scaffold[/] to create a default script")
|
|
157
|
+
sys.exit(1)
|
|
158
|
+
|
|
159
|
+
# Set environment variables for the server configuration
|
|
160
|
+
os.environ["SUPERVAIZER_HOST"] = host
|
|
161
|
+
os.environ["SUPERVAIZER_PORT"] = str(port)
|
|
162
|
+
os.environ["SUPERVAIZER_ENVIRONMENT"] = environment
|
|
163
|
+
os.environ["SUPERVAIZER_PERSISTENCE"] = str(persist).lower()
|
|
164
|
+
os.environ["SUPERVAIZER_LOG_LEVEL"] = log_level
|
|
165
|
+
os.environ["SUPERVAIZER_DEBUG"] = str(debug)
|
|
166
|
+
os.environ["SUPERVAIZER_RELOAD"] = str(reload)
|
|
167
|
+
if public_url is not None:
|
|
168
|
+
os.environ["SUPERVAIZER_PUBLIC_URL"] = public_url
|
|
169
|
+
|
|
170
|
+
console.print(f"[bold green]Starting Supervaizer Controller v{VERSION}[/]")
|
|
171
|
+
console.print(f"Loading configuration from [bold]{script_path}[/]")
|
|
172
|
+
|
|
173
|
+
# Execute the script in a new Python process with proper signal handling
|
|
174
|
+
|
|
175
|
+
def signal_handler(signum: int, frame: Any) -> None:
|
|
176
|
+
# Send the signal to the subprocess
|
|
177
|
+
if "process" in globals():
|
|
178
|
+
globals()["process"].terminate()
|
|
179
|
+
sys.exit(0)
|
|
180
|
+
|
|
181
|
+
signal.signal(signal.SIGINT, signal_handler)
|
|
182
|
+
signal.signal(signal.SIGTERM, signal_handler)
|
|
183
|
+
|
|
184
|
+
process = subprocess.Popen([sys.executable, script_path])
|
|
185
|
+
globals()["process"] = process
|
|
186
|
+
process.wait()
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _create_instructions_file(
|
|
190
|
+
output_dir: Path, force: bool = False, silent: bool = False
|
|
191
|
+
) -> Path:
|
|
192
|
+
"""Create supervaize_instructions.html file in the given directory.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
output_dir: Directory where to create the instructions file
|
|
196
|
+
force: If True, overwrite existing file
|
|
197
|
+
silent: If True, don't show warnings if file already exists (just skip)
|
|
198
|
+
"""
|
|
199
|
+
instructions_path = output_dir / "supervaize_instructions.html"
|
|
200
|
+
|
|
201
|
+
# Check if file already exists
|
|
202
|
+
if instructions_path.exists() and not force:
|
|
203
|
+
if not silent:
|
|
204
|
+
console.print(
|
|
205
|
+
f"[bold yellow]Warning:[/] {instructions_path} already exists"
|
|
206
|
+
)
|
|
207
|
+
console.print(
|
|
208
|
+
"Use [bold]--force[/] to overwrite it, or run [bold]supervaizer refresh-instructions[/]"
|
|
209
|
+
)
|
|
210
|
+
return instructions_path
|
|
211
|
+
|
|
212
|
+
# Get the path to the admin templates directory
|
|
213
|
+
admin_templates_dir = Path(__file__).parent / "admin" / "templates"
|
|
214
|
+
template_file = admin_templates_dir / "supervaize_instructions.html"
|
|
215
|
+
|
|
216
|
+
if not template_file.exists():
|
|
217
|
+
console.print("[bold red]Error:[/] Template file not found")
|
|
218
|
+
sys.exit(1)
|
|
219
|
+
|
|
220
|
+
# Copy the template file
|
|
221
|
+
shutil.copy(template_file, instructions_path)
|
|
222
|
+
return instructions_path
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
@scaffold_app.callback(invoke_without_command=True)
|
|
226
|
+
def scaffold(
|
|
227
|
+
ctx: typer.Context,
|
|
228
|
+
output_path: str = typer.Option(
|
|
229
|
+
os.environ.get("SUPERVAIZER_OUTPUT_PATH", "supervaizer_control.py"),
|
|
230
|
+
help="Path to save the script",
|
|
231
|
+
),
|
|
232
|
+
force: bool = typer.Option(
|
|
233
|
+
(os.environ.get("SUPERVAIZER_FORCE_INSTALL") or "False").lower() == "true",
|
|
234
|
+
help="Overwrite existing file",
|
|
235
|
+
),
|
|
236
|
+
) -> None:
|
|
237
|
+
"""Create a draft supervaizer_control.py script and supervaize_instructions.html."""
|
|
238
|
+
# Only run if no subcommand was invoked
|
|
239
|
+
if ctx.invoked_subcommand is not None:
|
|
240
|
+
return
|
|
241
|
+
# Check if file already exists
|
|
242
|
+
if os.path.exists(output_path) and not force:
|
|
243
|
+
console.print(f"[bold red]Error:[/] {output_path} already exists")
|
|
244
|
+
console.print("Use [bold]--force[/] to overwrite it")
|
|
245
|
+
sys.exit(1)
|
|
246
|
+
|
|
247
|
+
# Get the path to the examples directory
|
|
248
|
+
examples_dir = Path(__file__).parent / "examples"
|
|
249
|
+
example_file = examples_dir / "controller_template.py"
|
|
250
|
+
|
|
251
|
+
if not example_file.exists():
|
|
252
|
+
console.print("[bold red]Error:[/] Example file not found")
|
|
253
|
+
sys.exit(1)
|
|
254
|
+
|
|
255
|
+
# Copy the example file to the output path
|
|
256
|
+
shutil.copy(example_file, output_path)
|
|
257
|
+
console.print(
|
|
258
|
+
f"[bold green]Success:[/] Created an example file at [bold blue]{output_path}[/]"
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
# Create instructions file in the same directory (silently if it already exists)
|
|
262
|
+
output_dir = Path(output_path).parent
|
|
263
|
+
instructions_path = output_dir / "supervaize_instructions.html"
|
|
264
|
+
instructions_existed = instructions_path.exists()
|
|
265
|
+
_create_instructions_file(output_dir, force=force, silent=True)
|
|
266
|
+
# Only show success message if we actually created the file (didn't exist before or force was used)
|
|
267
|
+
if not instructions_existed or force:
|
|
268
|
+
console.print(
|
|
269
|
+
f"[bold green]Success:[/] Created instructions template at [bold blue]{instructions_path}[/]"
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
console.print(
|
|
273
|
+
"1. Copy this file to [bold]supervaizer_control.py[/] and edit it to configure your agent(s)"
|
|
274
|
+
)
|
|
275
|
+
console.print(
|
|
276
|
+
"2. Customize [bold]supervaize_instructions.html[/] to match your agent's documentation"
|
|
277
|
+
)
|
|
278
|
+
console.print(
|
|
279
|
+
"3. (Optional) Get your API from [bold]supervaizer.com and setup your environment variables"
|
|
280
|
+
)
|
|
281
|
+
console.print(
|
|
282
|
+
"4. Run [bold]supervaizer start[/] to start the supervaizer controller"
|
|
283
|
+
)
|
|
284
|
+
console.print("5. Open [bold]http://localhost:8000/docs[/] to explore the API")
|
|
285
|
+
sys.exit(0)
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
@scaffold_app.command(name="instructions")
|
|
289
|
+
def scaffold_instructions(
|
|
290
|
+
control_file: Optional[str] = typer.Option(
|
|
291
|
+
None,
|
|
292
|
+
help="Path to supervaizer_control.py (default: auto-detect)",
|
|
293
|
+
),
|
|
294
|
+
output_path: Optional[str] = typer.Option(
|
|
295
|
+
None,
|
|
296
|
+
help="Path to save supervaize_instructions.html (default: same directory as control file)",
|
|
297
|
+
),
|
|
298
|
+
force: bool = typer.Option(
|
|
299
|
+
False,
|
|
300
|
+
help="Overwrite existing file",
|
|
301
|
+
),
|
|
302
|
+
) -> None:
|
|
303
|
+
"""Create supervaize_instructions.html file."""
|
|
304
|
+
# Determine control file path
|
|
305
|
+
if control_file is None:
|
|
306
|
+
control_file = (
|
|
307
|
+
os.environ.get("SUPERVAIZER_SCRIPT_PATH") or "supervaizer_control.py"
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
control_path = Path(control_file)
|
|
311
|
+
|
|
312
|
+
# Determine output directory
|
|
313
|
+
if output_path is None:
|
|
314
|
+
output_dir = control_path.parent
|
|
315
|
+
instructions_path = output_dir / "supervaize_instructions.html"
|
|
316
|
+
else:
|
|
317
|
+
instructions_path = Path(output_path)
|
|
318
|
+
output_dir = instructions_path.parent
|
|
319
|
+
|
|
320
|
+
# Check if control file exists (informational)
|
|
321
|
+
if not control_path.exists():
|
|
322
|
+
console.print(f"[bold yellow]Warning:[/] Control file {control_file} not found")
|
|
323
|
+
console.print("Creating instructions file anyway...")
|
|
324
|
+
|
|
325
|
+
# Create instructions file
|
|
326
|
+
_create_instructions_file(output_dir, force=force)
|
|
327
|
+
console.print(
|
|
328
|
+
f"[bold green]Success:[/] Created instructions template at [bold blue]{instructions_path}[/]"
|
|
329
|
+
)
|
|
330
|
+
console.print(
|
|
331
|
+
"Customize this file to match your agent's documentation and instructions."
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
@scaffold_app.command(name="refresh-instructions")
|
|
336
|
+
def refresh_instructions(
|
|
337
|
+
control_file: Optional[str] = typer.Option(
|
|
338
|
+
None,
|
|
339
|
+
help="Path to supervaizer_control.py (default: auto-detect)",
|
|
340
|
+
),
|
|
341
|
+
output_path: Optional[str] = typer.Option(
|
|
342
|
+
None,
|
|
343
|
+
help="Path to supervaize_instructions.html (default: same directory as control file)",
|
|
344
|
+
),
|
|
345
|
+
force: bool = typer.Option(
|
|
346
|
+
False,
|
|
347
|
+
help="Skip confirmation prompt",
|
|
348
|
+
),
|
|
349
|
+
) -> None:
|
|
350
|
+
"""Refresh/update supervaize_instructions.html file."""
|
|
351
|
+
# Determine control file path
|
|
352
|
+
if control_file is None:
|
|
353
|
+
control_file = (
|
|
354
|
+
os.environ.get("SUPERVAIZER_SCRIPT_PATH") or "supervaizer_control.py"
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
control_path = Path(control_file)
|
|
358
|
+
|
|
359
|
+
# Determine output path
|
|
360
|
+
if output_path is None:
|
|
361
|
+
output_dir = control_path.parent
|
|
362
|
+
instructions_path = output_dir / "supervaize_instructions.html"
|
|
363
|
+
else:
|
|
364
|
+
instructions_path = Path(output_path)
|
|
365
|
+
|
|
366
|
+
# Check if instructions file exists
|
|
367
|
+
if instructions_path.exists():
|
|
368
|
+
if not force:
|
|
369
|
+
console.print(
|
|
370
|
+
f"[bold yellow]Warning:[/] {instructions_path} already exists"
|
|
371
|
+
)
|
|
372
|
+
if not Confirm.ask(
|
|
373
|
+
"Delete existing file and create a fresh template?",
|
|
374
|
+
default=False,
|
|
375
|
+
):
|
|
376
|
+
console.print("[bold]Cancelled.[/]")
|
|
377
|
+
sys.exit(0)
|
|
378
|
+
|
|
379
|
+
# Delete existing file
|
|
380
|
+
instructions_path.unlink()
|
|
381
|
+
console.print(f"[bold]Deleted[/] existing {instructions_path}")
|
|
382
|
+
|
|
383
|
+
# Create new instructions file
|
|
384
|
+
output_dir = instructions_path.parent
|
|
385
|
+
_create_instructions_file(output_dir, force=True)
|
|
386
|
+
console.print(
|
|
387
|
+
f"[bold green]Success:[/] Created fresh instructions template at [bold blue]{instructions_path}[/]"
|
|
388
|
+
)
|
|
389
|
+
console.print(
|
|
390
|
+
"Customize this file to match your agent's documentation and instructions."
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
if __name__ == "__main__":
|
|
395
|
+
app()
|