chore: 迁移服务器前同步本地修改

This commit is contained in:
2026-08-05 21:26:13 +08:00
parent aa47a19e98
commit 1a914a2517
73 changed files with 908 additions and 1961 deletions
+10 -10
View File
@@ -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 -22
View File
@@ -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}")
+4 -18
View File
@@ -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()
}