weco 0.3.4__tar.gz → 0.3.5__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.
- {weco-0.3.4 → weco-0.3.5}/PKG-INFO +1 -1
- {weco-0.3.4 → weco-0.3.5}/pyproject.toml +1 -1
- {weco-0.3.4 → weco-0.3.5}/weco/optimizer.py +77 -51
- {weco-0.3.4 → weco-0.3.5}/weco/panels.py +0 -21
- {weco-0.3.4 → weco-0.3.5}/weco.egg-info/PKG-INFO +1 -1
- {weco-0.3.4 → weco-0.3.5}/.github/workflows/lint.yml +0 -0
- {weco-0.3.4 → weco-0.3.5}/.github/workflows/release.yml +0 -0
- {weco-0.3.4 → weco-0.3.5}/.gitignore +0 -0
- {weco-0.3.4 → weco-0.3.5}/LICENSE +0 -0
- {weco-0.3.4 → weco-0.3.5}/README.md +0 -0
- {weco-0.3.4 → weco-0.3.5}/assets/example-optimization.gif +0 -0
- {weco-0.3.4 → weco-0.3.5}/assets/weco.svg +0 -0
- {weco-0.3.4 → weco-0.3.5}/contributing.md +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/README.md +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/cuda/README.md +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/cuda/evaluate.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/cuda/module.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/cuda/requirements.txt +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/extract-line-plot/README.md +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/extract-line-plot/eval.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/extract-line-plot/guide.md +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/extract-line-plot/optimize.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/extract-line-plot/prepare_data.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/extract-line-plot/pyproject.toml +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/hello-world/README.md +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/hello-world/colab_notebook_walkthrough.ipynb +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/hello-world/evaluate.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/hello-world/module.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/hello-world/requirements.txt +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/prompt/README.md +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/prompt/eval.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/prompt/optimize.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/prompt/prompt_guide.md +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/spaceship-titanic/README.md +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/spaceship-titanic/competition_description.md +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/spaceship-titanic/data/sample_submission.csv +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/spaceship-titanic/data/test.csv +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/spaceship-titanic/data/train.csv +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/spaceship-titanic/evaluate.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/spaceship-titanic/train.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/triton/README.md +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/triton/evaluate.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/triton/module.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/examples/triton/requirements.txt +0 -0
- {weco-0.3.4 → weco-0.3.5}/setup.cfg +0 -0
- {weco-0.3.4 → weco-0.3.5}/weco/__init__.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/weco/api.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/weco/auth.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/weco/chatbot.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/weco/cli.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/weco/constants.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/weco/credits.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/weco/utils.py +0 -0
- {weco-0.3.4 → weco-0.3.5}/weco.egg-info/SOURCES.txt +0 -0
- {weco-0.3.4 → weco-0.3.5}/weco.egg-info/dependency_links.txt +0 -0
- {weco-0.3.4 → weco-0.3.5}/weco.egg-info/entry_points.txt +0 -0
- {weco-0.3.4 → weco-0.3.5}/weco.egg-info/requires.txt +0 -0
- {weco-0.3.4 → weco-0.3.5}/weco.egg-info/top_level.txt +0 -0
|
@@ -8,7 +8,7 @@ name = "weco"
|
|
|
8
8
|
authors = [{ name = "Weco AI Team", email = "contact@weco.ai" }]
|
|
9
9
|
description = "Documentation for `weco`, a CLI for using Weco AI's code optimizer."
|
|
10
10
|
readme = "README.md"
|
|
11
|
-
version = "0.3.
|
|
11
|
+
version = "0.3.5"
|
|
12
12
|
license = { file = "LICENSE" }
|
|
13
13
|
requires-python = ">=3.8"
|
|
14
14
|
dependencies = [
|
|
@@ -144,17 +144,25 @@ def execute_optimization(
|
|
|
144
144
|
"""
|
|
145
145
|
if console is None:
|
|
146
146
|
console = Console()
|
|
147
|
-
|
|
148
147
|
# Global variables for this optimization run
|
|
149
148
|
heartbeat_thread = None
|
|
150
149
|
stop_heartbeat_event = threading.Event()
|
|
151
150
|
current_run_id_for_heartbeat = None
|
|
152
151
|
current_auth_headers_for_heartbeat = {}
|
|
152
|
+
live_ref = None # Reference to the Live object for the optimization run
|
|
153
|
+
|
|
154
|
+
best_solution_code = None
|
|
155
|
+
original_source_code = None
|
|
153
156
|
|
|
154
157
|
# --- Signal Handler for this optimization run ---
|
|
155
158
|
def signal_handler(signum, frame):
|
|
159
|
+
nonlocal live_ref
|
|
160
|
+
|
|
161
|
+
if live_ref is not None:
|
|
162
|
+
live_ref.stop() # Stop the live update loop so that messages are printed to the console
|
|
163
|
+
|
|
156
164
|
signal_name = signal.Signals(signum).name
|
|
157
|
-
console.print(f"\n[bold yellow]Termination signal ({signal_name}) received. Shutting down...[/]")
|
|
165
|
+
console.print(f"\n[bold yellow]Termination signal ({signal_name}) received. Shutting down...[/]\n")
|
|
158
166
|
|
|
159
167
|
# Stop heartbeat thread
|
|
160
168
|
stop_heartbeat_event.set()
|
|
@@ -170,7 +178,7 @@ def execute_optimization(
|
|
|
170
178
|
details=f"Process terminated by signal {signal_name} ({signum}).",
|
|
171
179
|
auth_headers=current_auth_headers_for_heartbeat,
|
|
172
180
|
)
|
|
173
|
-
console.print(f"
|
|
181
|
+
console.print(f"[cyan]To resume this run, use:[/] [bold cyan]weco resume {current_run_id_for_heartbeat}[/]\n")
|
|
174
182
|
|
|
175
183
|
# Exit gracefully
|
|
176
184
|
sys.exit(0)
|
|
@@ -183,8 +191,6 @@ def execute_optimization(
|
|
|
183
191
|
optimization_completed_normally = False
|
|
184
192
|
user_stop_requested_flag = False
|
|
185
193
|
|
|
186
|
-
best_solution_code = None
|
|
187
|
-
original_source_code = None # Make available to the finally block
|
|
188
194
|
try:
|
|
189
195
|
# --- Login/Authentication Handling (now mandatory) ---
|
|
190
196
|
weco_api_key, auth_headers = handle_authentication(console)
|
|
@@ -256,6 +262,7 @@ def execute_optimization(
|
|
|
256
262
|
# --- Live Update Loop ---
|
|
257
263
|
refresh_rate = 4
|
|
258
264
|
with Live(layout, refresh_per_second=refresh_rate) as live:
|
|
265
|
+
live_ref = live
|
|
259
266
|
# Define the runs directory (.runs/<run-id>) to store logs and results
|
|
260
267
|
runs_dir = pathlib.Path(log_dir) / run_id
|
|
261
268
|
runs_dir.mkdir(parents=True, exist_ok=True)
|
|
@@ -387,6 +394,16 @@ def execute_optimization(
|
|
|
387
394
|
status_response=status_response, solution_id=eval_and_next_solution_response["solution_id"]
|
|
388
395
|
)
|
|
389
396
|
|
|
397
|
+
# Set best solution and save optimization results
|
|
398
|
+
try:
|
|
399
|
+
best_solution_code = best_solution_node.code
|
|
400
|
+
except AttributeError:
|
|
401
|
+
# Can happen if the code was buggy
|
|
402
|
+
best_solution_code = read_from_path(fp=runs_dir / f"step_0{source_fp.suffix}", is_json=False)
|
|
403
|
+
|
|
404
|
+
# Save best solution to .runs/<run-id>/best.<extension>
|
|
405
|
+
write_to_path(fp=runs_dir / f"best{source_fp.suffix}", content=best_solution_code)
|
|
406
|
+
|
|
390
407
|
# Update the solution panels with the current and best solution
|
|
391
408
|
solution_panels.update(current_node=current_solution_node, best_node=best_solution_node)
|
|
392
409
|
current_solution_panel, best_solution_panel = solution_panels.get_display(current_step=step)
|
|
@@ -443,10 +460,13 @@ def execute_optimization(
|
|
|
443
460
|
)
|
|
444
461
|
# No need to set any solution to unevaluated since we have finished the optimization
|
|
445
462
|
# and all solutions have been evaluated
|
|
446
|
-
# No
|
|
463
|
+
# No need to update the current solution panel since we have finished the optimization
|
|
447
464
|
# We only need to update the best solution panel
|
|
448
465
|
# Figure out if we have a best solution so far
|
|
449
466
|
best_solution_node = get_best_node_from_status(status_response=status_response)
|
|
467
|
+
best_solution_code = best_solution_node.code
|
|
468
|
+
# Save best solution to .runs/<run-id>/best.<extension>
|
|
469
|
+
write_to_path(fp=runs_dir / f"best{source_fp.suffix}", content=best_solution_code)
|
|
450
470
|
solution_panels.update(current_node=None, best_node=best_solution_node)
|
|
451
471
|
_, best_solution_panel = solution_panels.get_display(current_step=steps)
|
|
452
472
|
# Update the end optimization layout
|
|
@@ -459,17 +479,6 @@ def execute_optimization(
|
|
|
459
479
|
end_optimization_layout["tree"].update(tree_panel.get_display(is_done=True))
|
|
460
480
|
end_optimization_layout["best_solution"].update(best_solution_panel)
|
|
461
481
|
|
|
462
|
-
# Save optimization results
|
|
463
|
-
# If the best solution does not exist or is has not been measured at the end of the optimization
|
|
464
|
-
# save the original solution as the best solution
|
|
465
|
-
try:
|
|
466
|
-
best_solution_code = best_solution_node.code
|
|
467
|
-
except AttributeError:
|
|
468
|
-
best_solution_code = read_from_path(fp=runs_dir / f"step_0{source_fp.suffix}", is_json=False)
|
|
469
|
-
|
|
470
|
-
# Save best solution to .runs/<run-id>/best.<extension>
|
|
471
|
-
write_to_path(fp=runs_dir / f"best{source_fp.suffix}", content=best_solution_code)
|
|
472
|
-
|
|
473
482
|
# Mark as completed normally for the finally block
|
|
474
483
|
optimization_completed_normally = True
|
|
475
484
|
live.update(end_optimization_layout)
|
|
@@ -481,7 +490,7 @@ def execute_optimization(
|
|
|
481
490
|
except Exception:
|
|
482
491
|
error_message = str(e)
|
|
483
492
|
console.print(Panel(f"[bold red]Error: {error_message}", title="[bold red]Optimization Error", border_style="red"))
|
|
484
|
-
console.print(f"\n[cyan]To resume this run, use:[/] [bold cyan]weco resume {run_id}[/]")
|
|
493
|
+
console.print(f"\n[cyan]To resume this run, use:[/] [bold cyan]weco resume {run_id}[/]\n")
|
|
485
494
|
# Ensure optimization_completed_normally is False
|
|
486
495
|
optimization_completed_normally = False
|
|
487
496
|
finally:
|
|
@@ -508,20 +517,16 @@ def execute_optimization(
|
|
|
508
517
|
else "CLI terminated unexpectedly without a specific exception captured."
|
|
509
518
|
)
|
|
510
519
|
|
|
511
|
-
# raise Exception(best_solution_code, original_source_code)
|
|
512
520
|
if best_solution_code and best_solution_code != original_source_code:
|
|
513
521
|
# Determine whether to apply: automatically if --apply-change is set, otherwise ask user
|
|
514
|
-
should_apply = apply_change or
|
|
515
|
-
|
|
516
|
-
layout=end_optimization_layout,
|
|
517
|
-
question="Would you like to apply the best solution to the source file?",
|
|
518
|
-
default=True,
|
|
522
|
+
should_apply = apply_change or Confirm.ask(
|
|
523
|
+
"Would you like to apply the best solution to the source file?", default=True
|
|
519
524
|
)
|
|
520
525
|
if should_apply:
|
|
521
526
|
write_to_path(fp=source_fp, content=best_solution_code)
|
|
522
|
-
console.print("[green]Best solution applied to the source file.[/]\n")
|
|
527
|
+
console.print("\n[green]Best solution applied to the source file.[/]\n")
|
|
523
528
|
else:
|
|
524
|
-
console.print("[green]A better solution was not found. No changes to apply.[/]\n")
|
|
529
|
+
console.print("\n[green]A better solution was not found. No changes to apply.[/]\n")
|
|
525
530
|
|
|
526
531
|
report_termination(
|
|
527
532
|
run_id=run_id,
|
|
@@ -534,7 +539,7 @@ def execute_optimization(
|
|
|
534
539
|
# Handle exit
|
|
535
540
|
if user_stop_requested_flag:
|
|
536
541
|
console.print("[yellow]Run terminated by user request.[/]")
|
|
537
|
-
console.print(f"\n[cyan]To resume this run, use:[/] [bold cyan]weco resume {run_id}[/]")
|
|
542
|
+
console.print(f"\n[cyan]To resume this run, use:[/] [bold cyan]weco resume {run_id}[/]\n")
|
|
538
543
|
|
|
539
544
|
return optimization_completed_normally or user_stop_requested_flag
|
|
540
545
|
|
|
@@ -549,11 +554,19 @@ def resume_optimization(run_id: str, console: Optional[Console] = None, apply_ch
|
|
|
549
554
|
stop_heartbeat_event = threading.Event()
|
|
550
555
|
current_run_id_for_heartbeat = None
|
|
551
556
|
current_auth_headers_for_heartbeat = {}
|
|
557
|
+
live_ref = None # Reference to the Live object for the optimization run
|
|
558
|
+
|
|
559
|
+
best_solution_code = None
|
|
560
|
+
original_source_code = None
|
|
552
561
|
|
|
553
562
|
# Signal handler for this optimization run
|
|
554
563
|
def signal_handler(signum, frame):
|
|
564
|
+
nonlocal live_ref
|
|
565
|
+
if live_ref is not None:
|
|
566
|
+
live_ref.stop() # Stop the live update loop so that messages are printed to the console
|
|
567
|
+
|
|
555
568
|
signal_name = signal.Signals(signum).name
|
|
556
|
-
console.print(f"\n[bold yellow]Termination signal ({signal_name}) received. Shutting down...[/]")
|
|
569
|
+
console.print(f"\n[bold yellow]Termination signal ({signal_name}) received. Shutting down...[/]\n")
|
|
557
570
|
stop_heartbeat_event.set()
|
|
558
571
|
if heartbeat_thread and heartbeat_thread.is_alive():
|
|
559
572
|
heartbeat_thread.join(timeout=2)
|
|
@@ -565,7 +578,7 @@ def resume_optimization(run_id: str, console: Optional[Console] = None, apply_ch
|
|
|
565
578
|
details=f"Process terminated by signal {signal_name} ({signum}).",
|
|
566
579
|
auth_headers=current_auth_headers_for_heartbeat,
|
|
567
580
|
)
|
|
568
|
-
console.print(f"\n[cyan]To resume this run, use:[/] [bold cyan]weco resume {current_run_id_for_heartbeat}[/]")
|
|
581
|
+
console.print(f"\n[cyan]To resume this run, use:[/] [bold cyan]weco resume {current_run_id_for_heartbeat}[/]\n")
|
|
569
582
|
sys.exit(0)
|
|
570
583
|
|
|
571
584
|
# Set up signal handlers for this run
|
|
@@ -575,9 +588,6 @@ def resume_optimization(run_id: str, console: Optional[Console] = None, apply_ch
|
|
|
575
588
|
optimization_completed_normally = False
|
|
576
589
|
user_stop_requested_flag = False
|
|
577
590
|
|
|
578
|
-
best_solution_code = None
|
|
579
|
-
original_source_code = None
|
|
580
|
-
|
|
581
591
|
try:
|
|
582
592
|
# --- Login/Authentication Handling (now mandatory) ---
|
|
583
593
|
weco_api_key, auth_headers = handle_authentication(console)
|
|
@@ -659,9 +669,8 @@ def resume_optimization(run_id: str, console: Optional[Console] = None, apply_ch
|
|
|
659
669
|
source_fp.parent.mkdir(parents=True, exist_ok=True)
|
|
660
670
|
# Store the original content to restore after each evaluation
|
|
661
671
|
original_source_code = read_from_path(fp=source_fp, is_json=False) if source_fp.exists() else ""
|
|
662
|
-
|
|
672
|
+
# The code to restore is the code from the last step of the previous run
|
|
663
673
|
code_to_restore = resume_resp.get("code") or resume_resp.get("source_code") or ""
|
|
664
|
-
write_to_path(fp=source_fp, content=code_to_restore)
|
|
665
674
|
|
|
666
675
|
# Prepare UI panels
|
|
667
676
|
summary_panel = SummaryPanel(
|
|
@@ -687,12 +696,25 @@ def resume_optimization(run_id: str, console: Optional[Console] = None, apply_ch
|
|
|
687
696
|
best_solution_node = get_best_node_from_status(status_response=status)
|
|
688
697
|
current_solution_node = get_node_from_status(status_response=status, solution_id=resume_resp.get("solution_id"))
|
|
689
698
|
|
|
699
|
+
# If there's no best solution yet (baseline evaluation didn't complete),
|
|
700
|
+
# mark the current node as unevaluated so the tree renders correctly
|
|
701
|
+
if best_solution_node is None:
|
|
702
|
+
tree_panel.set_unevaluated_node(node_id=resume_resp.get("solution_id"))
|
|
703
|
+
|
|
690
704
|
# Ensure runs dir exists
|
|
691
705
|
runs_dir = pathlib.Path(log_dir) / resume_resp["run_id"]
|
|
692
706
|
runs_dir.mkdir(parents=True, exist_ok=True)
|
|
693
707
|
# Persist last step's code into logs as step_<current_step>
|
|
694
708
|
write_to_path(fp=runs_dir / f"step_{current_step}{source_fp.suffix}", content=code_to_restore)
|
|
695
709
|
|
|
710
|
+
# Initialize best solution code
|
|
711
|
+
try:
|
|
712
|
+
best_solution_code = best_solution_node.code
|
|
713
|
+
except AttributeError:
|
|
714
|
+
# Edge case: best solution node is not available.
|
|
715
|
+
# This can happen if the user has cancelled the run before even running the baseline solution
|
|
716
|
+
pass # Leave best solution code as None
|
|
717
|
+
|
|
696
718
|
# Start Heartbeat Thread
|
|
697
719
|
stop_heartbeat_event.clear()
|
|
698
720
|
heartbeat_thread = HeartbeatSender(resume_resp["run_id"], auth_headers, stop_heartbeat_event)
|
|
@@ -705,6 +727,7 @@ def resume_optimization(run_id: str, console: Optional[Console] = None, apply_ch
|
|
|
705
727
|
# --- Live UI ---
|
|
706
728
|
refresh_rate = 4
|
|
707
729
|
with Live(layout, refresh_per_second=refresh_rate) as live:
|
|
730
|
+
live_ref = live
|
|
708
731
|
# Initial panels
|
|
709
732
|
current_solution_panel, best_solution_panel = solution_panels.get_display(current_step=current_step)
|
|
710
733
|
# Use backend-provided execution output only (no fallback)
|
|
@@ -788,6 +811,16 @@ def resume_optimization(run_id: str, console: Optional[Console] = None, apply_ch
|
|
|
788
811
|
status_response=status_response, solution_id=eval_and_next_solution_response["solution_id"]
|
|
789
812
|
)
|
|
790
813
|
|
|
814
|
+
# Set best solution and save optimization results
|
|
815
|
+
try:
|
|
816
|
+
best_solution_code = best_solution_node.code
|
|
817
|
+
except AttributeError:
|
|
818
|
+
# Can happen if the code was buggy
|
|
819
|
+
best_solution_code = read_from_path(fp=runs_dir / f"step_0{source_fp.suffix}", is_json=False)
|
|
820
|
+
|
|
821
|
+
# Save best solution to .runs/<run-id>/best.<extension>
|
|
822
|
+
write_to_path(fp=runs_dir / f"best{source_fp.suffix}", content=best_solution_code)
|
|
823
|
+
|
|
791
824
|
solution_panels.update(current_node=current_solution_node, best_node=best_solution_node)
|
|
792
825
|
current_solution_panel, best_solution_panel = solution_panels.get_display(current_step=step)
|
|
793
826
|
eval_output_panel.clear()
|
|
@@ -839,6 +872,10 @@ def resume_optimization(run_id: str, console: Optional[Console] = None, apply_ch
|
|
|
839
872
|
tree_panel.build_metric_tree(nodes=nodes_final)
|
|
840
873
|
# Best solution panel and final message
|
|
841
874
|
best_solution_node = get_best_node_from_status(status_response=status_response)
|
|
875
|
+
best_solution_code = best_solution_node.code
|
|
876
|
+
# Save best solution to .runs/<run-id>/best.<extension>
|
|
877
|
+
write_to_path(fp=runs_dir / f"best{source_fp.suffix}", content=best_solution_code)
|
|
878
|
+
|
|
842
879
|
solution_panels.update(current_node=None, best_node=best_solution_node)
|
|
843
880
|
_, best_solution_panel = solution_panels.get_display(current_step=total_steps)
|
|
844
881
|
final_message = (
|
|
@@ -850,14 +887,6 @@ def resume_optimization(run_id: str, console: Optional[Console] = None, apply_ch
|
|
|
850
887
|
end_optimization_layout["tree"].update(tree_panel.get_display(is_done=True))
|
|
851
888
|
end_optimization_layout["best_solution"].update(best_solution_panel)
|
|
852
889
|
|
|
853
|
-
# Save best
|
|
854
|
-
try:
|
|
855
|
-
best_solution_code = best_solution_node.code
|
|
856
|
-
except AttributeError:
|
|
857
|
-
best_solution_code = read_from_path(fp=runs_dir / f"step_0{source_fp.suffix}", is_json=False)
|
|
858
|
-
|
|
859
|
-
write_to_path(fp=runs_dir / f"best{source_fp.suffix}", content=best_solution_code)
|
|
860
|
-
|
|
861
890
|
optimization_completed_normally = True
|
|
862
891
|
live.update(end_optimization_layout)
|
|
863
892
|
|
|
@@ -867,7 +896,7 @@ def resume_optimization(run_id: str, console: Optional[Console] = None, apply_ch
|
|
|
867
896
|
except Exception:
|
|
868
897
|
error_message = str(e)
|
|
869
898
|
console.print(Panel(f"[bold red]Error: {error_message}", title="[bold red]Optimization Error", border_style="red"))
|
|
870
|
-
console.print(f"\n[cyan]To resume this run, use:[/] [bold cyan]weco resume {run_id}[/]")
|
|
899
|
+
console.print(f"\n[cyan]To resume this run, use:[/] [bold cyan]weco resume {run_id}[/]\n")
|
|
871
900
|
optimization_completed_normally = False
|
|
872
901
|
finally:
|
|
873
902
|
signal.signal(signal.SIGINT, original_sigint_handler)
|
|
@@ -896,17 +925,14 @@ def resume_optimization(run_id: str, console: Optional[Console] = None, apply_ch
|
|
|
896
925
|
)
|
|
897
926
|
|
|
898
927
|
if best_solution_code and best_solution_code != original_source_code:
|
|
899
|
-
should_apply = apply_change or
|
|
900
|
-
|
|
901
|
-
layout=end_optimization_layout,
|
|
902
|
-
question="Would you like to apply the best solution to the source file?",
|
|
903
|
-
default=True,
|
|
928
|
+
should_apply = apply_change or Confirm.ask(
|
|
929
|
+
"Would you like to apply the best solution to the source file?", default=True
|
|
904
930
|
)
|
|
905
931
|
if should_apply:
|
|
906
932
|
write_to_path(fp=source_fp, content=best_solution_code)
|
|
907
|
-
console.print("[green]Best solution applied to the source file.[/]\n")
|
|
933
|
+
console.print("\n[green]Best solution applied to the source file.[/]\n")
|
|
908
934
|
else:
|
|
909
|
-
console.print("[green]A better solution was not found. No changes to apply.[/]\n")
|
|
935
|
+
console.print("\n[green]A better solution was not found. No changes to apply.[/]\n")
|
|
910
936
|
|
|
911
937
|
report_termination(
|
|
912
938
|
run_id=run_id,
|
|
@@ -917,5 +943,5 @@ def resume_optimization(run_id: str, console: Optional[Console] = None, apply_ch
|
|
|
917
943
|
)
|
|
918
944
|
if user_stop_requested_flag:
|
|
919
945
|
console.print("[yellow]Run terminated by user request.[/]")
|
|
920
|
-
console.print(f"\n[cyan]To resume this run, use:[/] [bold cyan]weco resume {run_id}[/]")
|
|
946
|
+
console.print(f"\n[cyan]To resume this run, use:[/] [bold cyan]weco resume {run_id}[/]\n")
|
|
921
947
|
return optimization_completed_normally or user_stop_requested_flag
|
|
@@ -6,9 +6,7 @@ from rich.panel import Panel
|
|
|
6
6
|
from rich.syntax import Syntax
|
|
7
7
|
from rich import box
|
|
8
8
|
from rich.console import Console
|
|
9
|
-
from rich.live import Live
|
|
10
9
|
|
|
11
|
-
from rich.prompt import Confirm
|
|
12
10
|
from typing import Dict, List, Optional, Union, Tuple
|
|
13
11
|
from pathlib import Path
|
|
14
12
|
from .__init__ import __dashboard_url__
|
|
@@ -74,25 +72,6 @@ class SummaryPanel:
|
|
|
74
72
|
"""Clear the thinking content."""
|
|
75
73
|
self.thinking_content = ""
|
|
76
74
|
|
|
77
|
-
def ask_user_feedback(self, live: Live, layout: Layout, question: str, default: bool = True) -> bool:
|
|
78
|
-
"""
|
|
79
|
-
Ask a yes/no question while keeping the main layout fixed.
|
|
80
|
-
Uses Rich's Confirm for a clean user experience.
|
|
81
|
-
"""
|
|
82
|
-
# Stop live updates temporarily to prevent layout from moving
|
|
83
|
-
live.stop()
|
|
84
|
-
|
|
85
|
-
try:
|
|
86
|
-
# Use Rich's built-in Confirm
|
|
87
|
-
result = Confirm.ask(question, default=default)
|
|
88
|
-
except (KeyboardInterrupt, EOFError):
|
|
89
|
-
result = default
|
|
90
|
-
finally:
|
|
91
|
-
# Resume live updates
|
|
92
|
-
live.start()
|
|
93
|
-
|
|
94
|
-
return result
|
|
95
|
-
|
|
96
75
|
def get_display(self, final_message: Optional[str] = None) -> Panel:
|
|
97
76
|
"""Return a Rich panel summarising the current run."""
|
|
98
77
|
# ───────────────────── summary grid ──────────────────────
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|