Initial commit
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
"""Custom/org runtime entrypoint.
|
||||
|
||||
Custom mode runs with company-mode semantics, but with a user-selected
|
||||
organization config. The runner owns the custom isolation boundary:
|
||||
|
||||
- company mode's engine/config objects are not mutated;
|
||||
- the custom runtime uses its own OPCEngine instance and company executor;
|
||||
- the runtime is rebound to the caller's store so UI session/task/transcript
|
||||
state remains in the same project context as the chat that started it.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import uuid
|
||||
from typing import Any, TYPE_CHECKING
|
||||
|
||||
from opc.core.config import OPCConfig
|
||||
from opc.core.models import UserMessage
|
||||
from opc.core.org_config import (
|
||||
apply_org_config_payload_to_config,
|
||||
load_org_config_payload,
|
||||
validate_runnable_org_config,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from opc.engine import OPCEngine
|
||||
|
||||
|
||||
class CustomRuntimeRunner:
|
||||
"""Run custom/org turns through an isolated company-runtime engine."""
|
||||
|
||||
def __init__(self, parent: OPCEngine) -> None:
|
||||
self.parent = parent
|
||||
|
||||
def _build_org_config(self, organization_id: str | None) -> tuple[OPCConfig, str | None]:
|
||||
config_dir = self.parent.opc_home / "config"
|
||||
payload, source_path = load_org_config_payload(config_dir, organization_id)
|
||||
try:
|
||||
base_config = OPCConfig.load(config_dir) if config_dir.exists() else copy.deepcopy(self.parent.config)
|
||||
except Exception:
|
||||
base_config = copy.deepcopy(self.parent.config)
|
||||
loaded_config = apply_org_config_payload_to_config(
|
||||
base_config,
|
||||
payload,
|
||||
source_path=source_path,
|
||||
)
|
||||
resolved_org_id = str(getattr(loaded_config.org, "organization_id", "") or organization_id or "").strip() or None
|
||||
validate_runnable_org_config(loaded_config, organization_id=resolved_org_id or "")
|
||||
return loaded_config, resolved_org_id
|
||||
|
||||
async def process_message(
|
||||
self,
|
||||
content: str,
|
||||
*,
|
||||
project_id: str | None,
|
||||
session_id: str | None,
|
||||
org_id: str | None,
|
||||
preferred_agent: str | None,
|
||||
domains: list[str] | None,
|
||||
origin_task_id: str | None,
|
||||
attachment_refs: list[dict[str, Any]] | None,
|
||||
message_metadata: dict[str, Any] | None,
|
||||
) -> str:
|
||||
from opc.engine import OPCEngine
|
||||
from opc.layer2_organization.phase_hooks import unregister_dispatcher_wake
|
||||
|
||||
org_config, resolved_org_id = self._build_org_config(org_id)
|
||||
normalized_project_id = str(project_id or self.parent.project_id or "default").strip() or "default"
|
||||
shared_store = getattr(self.parent, "store", None)
|
||||
runtime = OPCEngine(
|
||||
config=org_config,
|
||||
opc_home=self.parent.opc_home,
|
||||
project_id=normalized_project_id,
|
||||
store=shared_store,
|
||||
owns_store=shared_store is None,
|
||||
run_startup_reconcile=shared_store is None,
|
||||
on_progress=self.parent.on_progress,
|
||||
on_runtime_event=self.parent.on_runtime_event,
|
||||
on_escalation=self.parent.on_escalation,
|
||||
)
|
||||
runtime.on_company_runtime_children = self.parent.on_company_runtime_children
|
||||
await runtime.initialize()
|
||||
company_executor = getattr(runtime, "company_executor", None)
|
||||
if company_executor is not None:
|
||||
callback_factory = getattr(self.parent, "on_company_kanban_callback_factory", None)
|
||||
if callable(callback_factory):
|
||||
company_executor.on_kanban_changed = callback_factory(runtime)
|
||||
else:
|
||||
parent_executor = getattr(self.parent, "company_executor", None)
|
||||
company_executor.on_kanban_changed = getattr(parent_executor, "on_kanban_changed", None)
|
||||
|
||||
try:
|
||||
normalized_attachment_refs = runtime._normalize_attachment_refs(attachment_refs)
|
||||
metadata = {
|
||||
"mode": "company",
|
||||
"exec_mode": "org",
|
||||
"org_id": resolved_org_id,
|
||||
"organization_id": resolved_org_id,
|
||||
"organization_name": str(getattr(org_config.org, "organization_name", "") or "").strip(),
|
||||
"organization_config_file": str(getattr(org_config.org, "organization_config_file", "") or "").strip(),
|
||||
"preferred_agent": preferred_agent,
|
||||
"domains": domains or [],
|
||||
"company_profile": "custom",
|
||||
"origin_task_id": origin_task_id,
|
||||
"attachment_refs": normalized_attachment_refs,
|
||||
}
|
||||
if message_metadata:
|
||||
metadata.update(dict(message_metadata))
|
||||
metadata["mode"] = "company"
|
||||
metadata["exec_mode"] = "org"
|
||||
metadata["company_profile"] = "custom"
|
||||
metadata["org_id"] = resolved_org_id
|
||||
metadata["organization_id"] = resolved_org_id
|
||||
|
||||
message = UserMessage(
|
||||
channel="cli",
|
||||
user_id="owner",
|
||||
content=content,
|
||||
attachments=normalized_attachment_refs,
|
||||
session_id=session_id or str(uuid.uuid4()),
|
||||
project_context=normalized_project_id,
|
||||
metadata=metadata,
|
||||
)
|
||||
response = await runtime.message_bus.process_single(message)
|
||||
return response.content if response else "No response generated."
|
||||
finally:
|
||||
company_executor = getattr(runtime, "company_executor", None)
|
||||
wake = getattr(company_executor, "_signal_dispatcher_wake", None)
|
||||
if wake is not None:
|
||||
unregister_dispatcher_wake(wake)
|
||||
await runtime.shutdown()
|
||||
Reference in New Issue
Block a user