Files
Elydora-Python-SDK/elydora/plugins/kiroide.py
T
雷电芽衣 6ec3e902f5 chore(python): audit providers kirocli kiroide opencode
Move Kiro IDE onto _runtime and _shell_command, share kirocli file
helpers through _file_io, and clean temp files on any interruption.

Claude-Session: https://claude.ai/code/session_01Agoc9bRVE9KL7mmWtey9Vq
2026-09-03 00:19:40 -04:00

134 lines
4.9 KiB
Python

"""Kiro IDE 1.0 workspace hook integration."""
from __future__ import annotations
from ._runtime import same_agent_id
from .base import AgentPlugin, InstallConfig, PluginStatus
from .kiroide_contract import (
AGENT_KEY,
AUDIT_NAME,
GUARD_NAME,
build_kiroide_hook,
kiroide_runtime_contracts,
managed_kiroide_hooks_present,
render_kiroide_document,
require_available_kiroide_hooks,
without_managed_kiroide_hooks,
)
from .kiroide_installation import (
commit_kiroide_installation,
commit_kiroide_uninstall,
preflight_kiroide_installation,
prepare_kiroide_installation,
prepare_kiroide_uninstall,
)
from .kiroide_io import (
kiroide_runtime_files_exist,
legacy_kiroide_contract_matches_agent,
read_kiroide_sources,
require_kiroide_workspace_owner,
)
class KiroIdePlugin(AgentPlugin):
"""Install Elydora into the active Kiro IDE workspace."""
manages_guard_runtime = True
manages_runtime_directories = True
manages_runtime_removal = True
def preflight_install(self, config: InstallConfig) -> None:
sources = read_kiroide_sources()
require_available_kiroide_hooks(sources.document.hooks)
preflight_kiroide_installation(config, sources)
def install(self, config: InstallConfig) -> None:
sources = read_kiroide_sources()
require_available_kiroide_hooks(sources.document.hooks)
paths = preflight_kiroide_installation(config, sources)
hooks = without_managed_kiroide_hooks(sources.document.hooks)
rendered = render_kiroide_document(
sources.document,
[
*hooks,
build_kiroide_hook(GUARD_NAME, paths.guard_path),
build_kiroide_hook(AUDIT_NAME, paths.audit_path),
],
)
prepared = prepare_kiroide_installation(
config, paths, sources, rendered
)
commit_kiroide_installation(prepared, sources, paths)
print(f" Kiro IDE workspace hooks: {sources.paths.config_path}")
print(
" Kiro IDE verification: confirm Elydora hooks in the "
"Agent Hooks panel."
)
def uninstall(self, agent_id: str = "") -> None:
sources = read_kiroide_sources()
contracts = kiroide_runtime_contracts(sources.document.hooks)
if agent_id:
discovered_agent_ids = [agent_id]
else:
discovered_agent_ids = [contract.agent_id for contract in contracts]
legacy_contract = sources.legacy.contract
if legacy_contract is not None:
discovered_agent_ids.append(legacy_contract.agent_id)
agent_ids: list[str] = []
for discovered_agent_id in discovered_agent_ids:
if not any(
same_agent_id(discovered_agent_id, existing_agent_id)
for existing_agent_id in agent_ids
):
agent_ids.append(discovered_agent_id)
for managed_agent_id in agent_ids:
owns_workspace_runtime = any(
same_agent_id(contract.agent_id, managed_agent_id)
for contract in contracts
)
require_kiroide_workspace_owner(
managed_agent_id,
sources.paths.workspace_root,
allow_missing_workspace_root=owns_workspace_runtime,
allow_legacy_ownerless_config=(
legacy_kiroide_contract_matches_agent(
sources.legacy, managed_agent_id
)
),
)
rendered = render_kiroide_document(
sources.document,
without_managed_kiroide_hooks(sources.document.hooks, agent_id),
)
prepared = prepare_kiroide_uninstall(
sources, rendered, agent_id, agent_ids
)
commit_kiroide_uninstall(prepared, sources)
print("Elydora hooks uninstalled from Kiro IDE.")
def status(self) -> PluginStatus:
sources = read_kiroide_sources()
require_available_kiroide_hooks(sources.document.hooks)
contracts = kiroide_runtime_contracts(sources.document.hooks)
configured = bool(contracts)
managed_present = managed_kiroide_hooks_present(sources.document.hooks)
installed = configured and kiroide_runtime_files_exist(
contracts, sources.paths.workspace_root
)
if installed:
details = f"Config: {sources.paths.config_path}"
elif configured:
details = (
f"Configured at {sources.paths.config_path}; "
"runtime files are missing or invalid"
)
elif managed_present:
details = (
f"Managed hooks are incomplete or invalid: "
f"{sources.paths.config_path}"
)
else:
details = "Not installed"
return PluginStatus(installed=installed, agent=AGENT_KEY, details=details)