chore: 迁移服务器前同步本地修改
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""BaseOrganization:重型插件基类。
|
||||
|
||||
设计要点:
|
||||
- 单机模式 = 普通 Python 对象,分布式 = ray actor(``@actor_class`` 装饰子类)
|
||||
- 进程内普通 Python 对象,经 ``register_actor`` 登记后由 ``get_actor`` 寻址
|
||||
- 内置 ``asyncio.Queue`` 输入队列 + 任务表
|
||||
- 对外两条通道:``dispatch`` (阻塞) / ``submit`` (射后不管),底层都汇集到 ``_run_task``
|
||||
- 子类只需覆写 ``setup`` / ``react`` 两个钩子;零代码插件由 ``agents.json`` 声明驱动
|
||||
@@ -335,10 +335,10 @@ class BaseOrganization:
|
||||
async def _persist_task(self, ts: TaskState) -> None:
|
||||
"""把任务状态写到 PG。失败不阻塞执行。"""
|
||||
try:
|
||||
from kilostar.utils.ray_hook import ray_actor_hook
|
||||
from kilostar.utils.actor import get_actor
|
||||
|
||||
pg = ray_actor_hook("postgres_database").postgres_database
|
||||
await pg.upsert_org_task.remote(
|
||||
pg = get_actor("postgres_database")
|
||||
await pg.upsert_org_task(
|
||||
task_id=ts.task_id,
|
||||
org_name=ts.org_name,
|
||||
trace_id=ts.trace_id,
|
||||
@@ -354,10 +354,10 @@ class BaseOrganization:
|
||||
|
||||
async def _persist_event(self, ts: TaskState, ev: OrgEvent) -> None:
|
||||
try:
|
||||
from kilostar.utils.ray_hook import ray_actor_hook
|
||||
from kilostar.utils.actor import get_actor
|
||||
|
||||
pg = ray_actor_hook("postgres_database").postgres_database
|
||||
await pg.append_org_task_event.remote(
|
||||
pg = get_actor("postgres_database")
|
||||
await pg.append_org_task_event(
|
||||
task_id=ts.task_id, event=ev.to_dict()
|
||||
)
|
||||
except Exception:
|
||||
@@ -510,10 +510,10 @@ class BaseOrganization:
|
||||
if adef.model and adef.model.provider_title and adef.model.model_id:
|
||||
return adef.model.provider_title, adef.model.model_id
|
||||
try:
|
||||
from kilostar.utils.ray_hook import ray_actor_hook
|
||||
from kilostar.utils.actor import get_actor
|
||||
|
||||
pg = ray_actor_hook("postgres_database").postgres_database
|
||||
row = await pg.find_plugin_slot.remote(self.name, adef.name)
|
||||
pg = get_actor("postgres_database")
|
||||
row = await pg.find_plugin_slot(self.name, adef.name)
|
||||
if row is None:
|
||||
return "", ""
|
||||
return getattr(row, "provider_title", "") or "", getattr(row, "model_id", "") or ""
|
||||
|
||||
@@ -19,18 +19,16 @@ from kilostar.plugin_runtime.loader import (
|
||||
from kilostar.plugin_runtime.manifest import OrgManifest
|
||||
from kilostar.plugin_runtime.tool_bridge import make_dispatch_tool
|
||||
from kilostar.utils.logger import get_logger
|
||||
from kilostar.utils.ray_compat import _STANDALONE, actor_class
|
||||
from kilostar.utils.ray_hook import register_standalone
|
||||
from kilostar.utils.actor import register_actor
|
||||
from kilostar.utils.settings import get_plugin_data_dir, get_plugin_dir
|
||||
|
||||
logger = get_logger("plugin_manager")
|
||||
|
||||
|
||||
@actor_class
|
||||
class GlobalPluginManager:
|
||||
"""单机模式下是对象,分布式下是 ray actor。
|
||||
"""插件运行时管理器(进程内单例)。
|
||||
|
||||
每个 loaded 组织保存其 manifest 和 actor handle(standalone=proxy,dist=ray handle)。
|
||||
每个 loaded 组织保存其 manifest 和实例,并注册到进程内 actor 运行时。
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
@@ -64,13 +62,18 @@ class GlobalPluginManager:
|
||||
org_info = self._orgs.pop(name, None)
|
||||
if org_info is None:
|
||||
return {"name": name, "status": "not_found"}
|
||||
# shutdown actor
|
||||
# shutdown 实例并从 actor 运行时注销
|
||||
try:
|
||||
handle = org_info.get("handle")
|
||||
if handle is not None:
|
||||
await handle.shutdown.remote()
|
||||
await handle.shutdown()
|
||||
except Exception as e:
|
||||
logger.warning(f"shutdown org_{name} failed: {e}")
|
||||
actor_name = org_info.get("actor_name")
|
||||
if actor_name:
|
||||
from kilostar.utils.actor import unregister_actor
|
||||
|
||||
unregister_actor(actor_name)
|
||||
# 移除 dispatch tool
|
||||
self._dispatch_tools.pop(f"dispatch_to_{name}", None)
|
||||
logger.info(f"uninstalled plugin: {name}")
|
||||
@@ -136,15 +139,9 @@ class GlobalPluginManager:
|
||||
|
||||
await instance.setup()
|
||||
|
||||
# 注册到 ray_actor_hook 命名空间
|
||||
# 注册到进程内 actor 运行时,业务侧通过 get_actor(actor_name) 取用
|
||||
actor_name = manifest.actor_name
|
||||
if _STANDALONE:
|
||||
register_standalone(actor_name, instance)
|
||||
else:
|
||||
# 分布式模式下,这里需要把 instance 包装成 ray actor
|
||||
# 第一版走 standalone 逻辑(两种模式统一 register 到本进程)
|
||||
# 真正分布式隔离等后续做
|
||||
register_standalone(actor_name, instance)
|
||||
register_actor(actor_name, instance)
|
||||
|
||||
# 生成 dispatch tool
|
||||
tool = make_dispatch_tool(name, manifest.display_name, manifest.description)
|
||||
@@ -166,15 +163,15 @@ class GlobalPluginManager:
|
||||
DB 不可用时静默跳过(standalone 启动早期 / 单测场景)。
|
||||
"""
|
||||
try:
|
||||
from kilostar.utils.ray_hook import ray_actor_hook
|
||||
from kilostar.utils.actor import get_actor
|
||||
|
||||
pg = ray_actor_hook("postgres_database").postgres_database
|
||||
pg = get_actor("postgres_database")
|
||||
for adef in agents_dict.get("agents", []):
|
||||
slot_name = adef.get("name")
|
||||
if not slot_name:
|
||||
continue
|
||||
description = adef.get("role") or adef.get("system_prompt") or slot_name
|
||||
await pg.upsert_plugin_slot.remote(
|
||||
await pg.upsert_plugin_slot(
|
||||
plugin_name=name,
|
||||
slot_name=slot_name,
|
||||
description=description,
|
||||
@@ -185,10 +182,10 @@ class GlobalPluginManager:
|
||||
async def cleanup_orphan_plugin_slots(self) -> None:
|
||||
"""启动期兜底:DB 中存在但目录已不在的 plugin_owned slot 全部清掉。"""
|
||||
try:
|
||||
from kilostar.utils.ray_hook import ray_actor_hook
|
||||
from kilostar.utils.actor import get_actor
|
||||
|
||||
pg = ray_actor_hook("postgres_database").postgres_database
|
||||
recorded: List[str] = await pg.list_plugin_owned_names.remote() or []
|
||||
pg = get_actor("postgres_database")
|
||||
recorded: List[str] = await pg.list_plugin_owned_names() or []
|
||||
except Exception as e:
|
||||
logger.debug(f"cleanup_orphan_plugin_slots skipped: {e}")
|
||||
return
|
||||
@@ -198,7 +195,7 @@ class GlobalPluginManager:
|
||||
for plugin_name in recorded:
|
||||
if plugin_name not in present:
|
||||
try:
|
||||
n = await pg.delete_plugin_slots.remote(plugin_name)
|
||||
n = await pg.delete_plugin_slots(plugin_name)
|
||||
logger.info(f"cleaned {n} orphan slots for missing plugin {plugin_name!r}")
|
||||
except Exception as e:
|
||||
logger.warning(f"failed to clean orphan slots for {plugin_name}: {e}")
|
||||
|
||||
@@ -6,7 +6,7 @@ RegulatoryNode/ConsciousnessNode 通过这个工具向部门派单,等待部
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Callable, Dict
|
||||
from typing import Callable
|
||||
|
||||
|
||||
def make_dispatch_tool(org_name: str, display_name: str, description: str) -> Callable:
|
||||
@@ -19,12 +19,10 @@ def make_dispatch_tool(org_name: str, display_name: str, description: str) -> Ca
|
||||
desc_text = description or f"把任务派给{display_name or org_name}部门,由部门内部多 agent 协作完成。"
|
||||
|
||||
async def _impl(task_description: str) -> str:
|
||||
from kilostar.utils.ray_hook import ray_actor_hook
|
||||
from kilostar.utils.actor import get_actor
|
||||
|
||||
actor_name = f"org_{org_name}"
|
||||
actor = ray_actor_hook(actor_name)
|
||||
target = getattr(actor, actor_name)
|
||||
result = await target.dispatch.remote(task_description, {})
|
||||
target = get_actor(f"org_{org_name}")
|
||||
result = await target.dispatch(task_description, {})
|
||||
if result.get("status") == "completed":
|
||||
return str(result.get("result") or "")
|
||||
return f"[{org_name} 任务失败] {result.get('error') or 'unknown'}"
|
||||
@@ -38,15 +36,3 @@ def make_dispatch_tool(org_name: str, display_name: str, description: str) -> Ca
|
||||
" 部门交付的结果文本,失败时返回错误说明。\n"
|
||||
)
|
||||
return _impl
|
||||
|
||||
|
||||
def collect_dispatch_tools(org_specs: Dict[str, Dict[str, str]]) -> Dict[str, Callable]:
|
||||
"""根据 ``{org_name: {"display_name": ..., "description": ...}}`` 批量生成。"""
|
||||
return {
|
||||
f"dispatch_to_{name}": make_dispatch_tool(
|
||||
name,
|
||||
spec.get("display_name", ""),
|
||||
spec.get("description", ""),
|
||||
)
|
||||
for name, spec in org_specs.items()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user