Files

102 lines
3.3 KiB
Python

"""Gemini CLI native global user-hook integration."""
from __future__ import annotations
from .base import AgentPlugin, InstallConfig, PluginStatus
from .gemini_config import GeminiDocument, render_gemini_document
from .gemini_contract import (
AGENT_KEY,
AUDIT_HOOK_NAME,
GUARD_HOOK_NAME,
build_gemini_group,
disabled_managed_gemini_entries,
gemini_runtime_contracts,
managed_gemini_hooks_enabled,
)
from .gemini_installation import (
commit_gemini_installation,
preflight_gemini_installation,
prepare_gemini_installation,
)
from .gemini_io import (
gemini_runtime_files_exist,
read_gemini_document,
write_gemini_document,
)
def _require_enabled_hooks(document: GeminiDocument) -> None:
if not document.hook_controls.enabled:
raise ValueError(
"Gemini CLI hooks are disabled by hooksConfig.enabled: "
f"{document.file_path}"
)
disabled = disabled_managed_gemini_entries(document.hook_controls)
if disabled:
raise ValueError(
"Gemini CLI hooks are disabled by hooksConfig.disabled: "
+ ", ".join(disabled)
)
class GeminiPlugin(AgentPlugin):
"""Install Elydora into Gemini CLI's native user settings."""
manages_guard_runtime = True
def preflight_install(self, config: InstallConfig) -> None:
document = read_gemini_document()
_require_enabled_hooks(document)
preflight_gemini_installation(config, document)
def install(self, config: InstallConfig) -> None:
document = read_gemini_document()
_require_enabled_hooks(document)
paths = preflight_gemini_installation(config, document)
rendered = render_gemini_document(
document,
None,
{
"BeforeTool": build_gemini_group(
paths.guard_path, GUARD_HOOK_NAME
),
"AfterTool": build_gemini_group(
paths.audit_path, AUDIT_HOOK_NAME
),
},
)
changes = prepare_gemini_installation(config, paths, rendered)
commit_gemini_installation(changes)
print(f"Gemini CLI hooks installed at {document.file_path}")
print("Gemini CLI verification: run /hooks list.")
def uninstall(self, agent_id: str = "") -> None:
document = read_gemini_document()
write_gemini_document(
render_gemini_document(document, agent_id or None, {})
)
def status(self) -> PluginStatus:
document = read_gemini_document()
contracts = gemini_runtime_contracts(document.hooks)
controls_enabled = managed_gemini_hooks_enabled(
document.hook_controls
)
configured = controls_enabled and bool(contracts)
installed = configured and gemini_runtime_files_exist(contracts)
if installed:
details = f"Config: {document.file_path}"
elif contracts and not controls_enabled:
details = f"Configured hooks are disabled: {document.file_path}"
elif contracts:
details = (
f"Configured at {document.file_path}; managed contract incomplete"
)
else:
details = "Not installed"
return PluginStatus(
installed=installed,
agent=AGENT_KEY,
details=details,
)