@@ -1847,7 +1847,7 @@ def _resolve_installed_extension(
18471847 for ext in name_matches :
18481848 table .add_row (ext .get ("id" , "" ), ext .get ("name" , "" ), str (ext .get ("version" , "" )))
18491849 console .print (table )
1850- console .print (f "\n Please rerun using the extension ID:" )
1850+ console .print ("\n Please rerun using the extension ID:" )
18511851 console .print (f" [bold]specify extension { command_name } <extension-id>[/bold]" )
18521852 raise typer .Exit (1 )
18531853 else :
@@ -1910,7 +1910,7 @@ def _resolve_catalog_extension(
19101910 ext .get ("_catalog_name" , "" ),
19111911 )
19121912 console .print (table )
1913- console .print (f "\n Please rerun using the extension ID:" )
1913+ console .print ("\n Please rerun using the extension ID:" )
19141914 console .print (f" [bold]specify extension { command_name } <extension-id>[/bold]" )
19151915 raise typer .Exit (1 )
19161916
@@ -2426,7 +2426,7 @@ def extension_info(
24262426 extension : str = typer .Argument (help = "Extension ID or name" ),
24272427):
24282428 """Show detailed information about an extension."""
2429- from .extensions import ExtensionCatalog , ExtensionManager , ExtensionError
2429+ from .extensions import ExtensionCatalog , ExtensionManager
24302430
24312431 project_root = Path .cwd ()
24322432
@@ -2488,7 +2488,7 @@ def extension_info(
24882488 console .print (f"[yellow]Catalog unavailable:[/yellow] { catalog_error } " )
24892489 console .print ("[dim]Note: Using locally installed extension; catalog info could not be verified.[/dim]" )
24902490 else :
2491- console .print (f "[yellow]Note:[/yellow] Not found in catalog (custom/local extension)" )
2491+ console .print ("[yellow]Note:[/yellow] Not found in catalog (custom/local extension)" )
24922492
24932493 console .print ()
24942494 console .print ("[green]✓ Installed[/green]" )
@@ -2649,6 +2649,9 @@ def extension_update(
26492649 for ext_id in extensions_to_update :
26502650 # Get installed version
26512651 metadata = manager .registry .get (ext_id )
2652+ if metadata is None or "version" not in metadata :
2653+ console .print (f"⚠ { ext_id } : Registry entry corrupted or missing (skipping)" )
2654+ continue
26522655 installed_version = pkg_version .Version (metadata ["version" ])
26532656
26542657 # Get catalog info
@@ -2803,7 +2806,14 @@ def extension_update(
28032806
28042807 # 9. Restore metadata from backup (installed_at, enabled state)
28052808 if backup_registry_entry :
2806- new_metadata = manager .registry .get (extension_id )
2809+ # Copy current registry entry to avoid mutating internal
2810+ # registry state before explicit restore().
2811+ current_metadata = manager .registry .get (extension_id )
2812+ if current_metadata is None :
2813+ raise RuntimeError (
2814+ f"Registry entry for '{ extension_id } ' missing after install — update incomplete"
2815+ )
2816+ new_metadata = dict (current_metadata )
28072817
28082818 # Preserve the original installation timestamp
28092819 if "installed_at" in backup_registry_entry :
@@ -2813,7 +2823,9 @@ def extension_update(
28132823 if not backup_registry_entry .get ("enabled" , True ):
28142824 new_metadata ["enabled" ] = False
28152825
2816- manager .registry .update (extension_id , new_metadata )
2826+ # Use restore() instead of update() because update() always
2827+ # preserves the existing installed_at, ignoring our override
2828+ manager .registry .restore (extension_id , new_metadata )
28172829
28182830 # Also disable hooks in extensions.yml if extension was disabled
28192831 if not backup_registry_entry .get ("enabled" , True ):
@@ -2860,7 +2872,10 @@ def extension_update(
28602872 # (files that weren't in the original backup)
28612873 try :
28622874 new_registry_entry = manager .registry .get (extension_id )
2863- new_registered_commands = new_registry_entry .get ("registered_commands" , {})
2875+ if new_registry_entry is None :
2876+ new_registered_commands = {}
2877+ else :
2878+ new_registered_commands = new_registry_entry .get ("registered_commands" , {})
28642879 for agent_name , cmd_names in new_registered_commands .items ():
28652880 if agent_name not in registrar .AGENT_CONFIGS :
28662881 continue
@@ -2926,7 +2941,7 @@ def extension_update(
29262941 if backup_registry_entry :
29272942 manager .registry .restore (extension_id , backup_registry_entry )
29282943
2929- console .print (f " [green]✓[/green] Rollback successful" )
2944+ console .print (" [green]✓[/green] Rollback successful" )
29302945 # Clean up backup directory only on successful rollback
29312946 if backup_base .exists ():
29322947 shutil .rmtree (backup_base )
@@ -2974,6 +2989,10 @@ def extension_enable(
29742989
29752990 # Update registry
29762991 metadata = manager .registry .get (extension_id )
2992+ if metadata is None :
2993+ console .print (f"[red]Error:[/red] Extension '{ extension_id } ' not found in registry (corrupted state)" )
2994+ raise typer .Exit (1 )
2995+
29772996 if metadata .get ("enabled" , True ):
29782997 console .print (f"[yellow]Extension '{ display_name } ' is already enabled[/yellow]" )
29792998 raise typer .Exit (0 )
@@ -3018,6 +3037,10 @@ def extension_disable(
30183037
30193038 # Update registry
30203039 metadata = manager .registry .get (extension_id )
3040+ if metadata is None :
3041+ console .print (f"[red]Error:[/red] Extension '{ extension_id } ' not found in registry (corrupted state)" )
3042+ raise typer .Exit (1 )
3043+
30213044 if not metadata .get ("enabled" , True ):
30223045 console .print (f"[yellow]Extension '{ display_name } ' is already disabled[/yellow]" )
30233046 raise typer .Exit (0 )
0 commit comments