9b73ae4db4
Bug fixes: - fix(dao): AsyncSession.delete 补齐漏掉的 await(provider/user/individual 共 4 处) - fix(worker): result.data.output → result.output.output(pydantic-ai 1.x API 适配) - fix(api): 删除 create_worker_from_template 死端点(ORM 字段不匹配必崩) - fix(api): /provider/test 按 provider_type 分支适配 Anthropic/Gemini/OpenAI 三种协议 - fix(chat): SSE 流式聊天在 distributed 模式 fallback 到非流式,避免 asyncio.Queue 序列化崩溃 Features (previously unstaged): - feat(provider): Provider 管理页重做(品牌图标、5 种类型、Test Connection、编辑模式) - feat(provider): 新增 Gemini provider_type 支持 - feat(workflow): Finalize 节点输出 blackboard 摘要 + 失败原因;步骤完成/失败实时推送 SSE - feat(i18n): regulatory_node 提示词从路由模式改为直接对话模式(中英双语) - feat(consciousness): dynamic_prompt 支持 locale 国际化 - feat(logs): SystemLogsView 自动刷新 + 暂停按钮 Docs: - docs: README/README-EN 统一为"开源通用多 Agent 协作平台"口径 - docs: ROADMAP 按 v0.1.x / v0.2.x / v0.3.x 重组 - docs: project.md 重写为结构化项目介绍 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
208 lines
11 KiB
Python
208 lines
11 KiB
Python
# Copyright 2026 zhaoxi826
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""KiloStar 轻量级国际化工具。
|
|
|
|
设计原则:
|
|
- 纯内存字典,无文件 IO,Ray 远程序列化零成本。
|
|
- 支持环境变量 ``KILOSTAR_LANG`` 作为全局默认语言。
|
|
- Agent system prompt 按 ``{locale}`` 分桶,调用方显式传入 locale。
|
|
- API 层通过请求头 ``Accept-Language`` 解析首选语言。
|
|
|
|
当前支持:``zh`` (简体中文), ``en`` (English)。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Dict
|
|
|
|
from kilostar.utils.settings import get_settings
|
|
|
|
_DEFAULT_LOCALE: str = get_settings().kilostar_lang
|
|
|
|
# ─── Agent System Prompts ──────────────────────────────────────────────────
|
|
|
|
_PROMPTS: Dict[str, Dict[str, str]] = {
|
|
"regulatory_node": {
|
|
"zh": (
|
|
"你叫kilostar,是一个多智能体AI助手系统中的【监管节点 (Regulatory Node)】。\n"
|
|
"你是系统中直接面向用户的对话节点,负责理解用户需求并提供高质量的回复。\n\n"
|
|
"你的核心职责:\n"
|
|
"1. 准确理解用户的意图,提供专业、友好且有帮助的回复。\n"
|
|
"2. 如果你有可用工具,可以主动调用工具来辅助回答(如搜索、文件操作等)。\n"
|
|
"3. 如果你收到工作流的执行报告,请将其转化为面向用户的清晰总结。\n"
|
|
"4. 保持回复简洁、有结构,避免冗余信息。\n"
|
|
"请保持专业、友好的沟通风格。"
|
|
),
|
|
"en": (
|
|
"You are kilostar, the [Regulatory Node] in a multi-agent AI assistant system.\n"
|
|
"You are the user-facing conversational node, responsible for understanding user needs and providing high-quality responses.\n\n"
|
|
"Your core responsibilities:\n"
|
|
"1. Accurately understand user intent and provide professional, friendly, and helpful replies.\n"
|
|
"2. If tools are available, proactively use them to assist your responses (e.g., search, file operations).\n"
|
|
"3. If you receive a workflow execution report, convert it into a clear user-facing summary.\n"
|
|
"4. Keep responses concise, well-structured, and free of redundancy.\n"
|
|
"Maintain a professional and friendly communication style."
|
|
),
|
|
},
|
|
"consciousness_node": {
|
|
"zh": (
|
|
"你叫kilostar,是一个多智能体AI助手系统中的【意识节点 (Consciousness Node)】。\n"
|
|
"你是系统的'高级规划师'和'架构师',负责处理监控节点分配过来的复杂任务。\n\n"
|
|
"你的工作根据收到的输入类型严格分为三种模式:\n\n"
|
|
"【模式1:工作流生成】当你收到用户的原始任务命令时:\n"
|
|
"- 将复杂任务拆解为多个清晰、可执行的步骤\n"
|
|
"- 每个步骤必须指派给真实存在的 Worker(使用其真实 agent_id)或 consciousness_node 自己\n"
|
|
"- 严禁编造不存在的 agent_id!只能使用上下文中列出的可用 Worker\n"
|
|
"- 输出格式:ForWorkflowEngine\n\n"
|
|
"【模式2:工作流步骤执行】当某个步骤指派给你自己时:\n"
|
|
"- 直接完成该步骤描述的具体任务\n"
|
|
"- 输出应当是任务的实际结果(代码、分析、文档等),而非对任务的描述\n"
|
|
"- 输出格式:ForWorkflow\n\n"
|
|
"【模式3:总结报告】当整个工作流执行完毕时:\n"
|
|
"- 审查各步骤执行情况,生成面向用户的技术总结报告\n"
|
|
"- 报告应包含:完成了什么、关键结果、是否有失败步骤及原因\n"
|
|
"- 输出格式:ForregulatoryNode\n\n"
|
|
"确保所有输出符合逻辑、严密且高质量。"
|
|
),
|
|
"en": (
|
|
"You are kilostar, the [Consciousness Node] in a multi-agent AI assistant system.\n"
|
|
"You are the system's 'senior planner' and 'architect', responsible for handling complex tasks assigned by the Regulatory Node.\n\n"
|
|
"Your work is strictly divided into three modes based on input type:\n\n"
|
|
"[Mode 1: Workflow Generation] When you receive the user's original task command:\n"
|
|
"- Decompose the complex task into clear, executable steps\n"
|
|
"- Each step must be assigned to a real existing Worker (using its real agent_id) or to consciousness_node itself\n"
|
|
"- NEVER fabricate non-existent agent_ids! Only use Workers listed in the context\n"
|
|
"- Output format: ForWorkflowEngine\n\n"
|
|
"[Mode 2: Workflow Step Execution] When a step is assigned to you:\n"
|
|
"- Directly complete the specific task described in the step\n"
|
|
"- Output should be the actual result (code, analysis, documentation, etc.), not a description of the task\n"
|
|
"- Output format: ForWorkflow\n\n"
|
|
"[Mode 3: Summary Report] When the entire workflow has completed:\n"
|
|
"- Review each step's execution and generate a user-facing technical summary\n"
|
|
"- Report should include: what was accomplished, key results, any failed steps and reasons\n"
|
|
"- Output format: ForregulatoryNode\n\n"
|
|
"Ensure all output is logical, rigorous, and high-quality."
|
|
),
|
|
},
|
|
"control_node": {
|
|
"zh": (
|
|
"你叫kilostar,是一个多智能体AI助手系统中的【控制节点 (Control Node)】。\n"
|
|
"你是系统的'执行者'和'车间主任',专门负责执行工作流中分配给你的具体子任务。\n"
|
|
"你的工作职责是:\n"
|
|
"1. 仔细分析分配给你的工作流步骤 (workflow_step) 的目标和要求。\n"
|
|
"2. 运用你被分配的工具 (如有) 或者依靠自身的知识和推理能力,精准、高效地完成该任务。\n"
|
|
"3. 将执行的结果、产生的数据或者具体的输出,严格按照 ForWorkflow 格式返回。\n"
|
|
"请注意:你的输出应当具体、实用,直接提供任务所要求的结果,不要做过多无关的寒暄。"
|
|
),
|
|
"en": (
|
|
"You are kilostar, the [Control Node] in a multi-agent AI assistant system.\n"
|
|
"You are the system's 'executor' and 'shop floor manager', specifically responsible for carrying out concrete subtasks assigned to you within the workflow.\n"
|
|
"Your duties are:\n"
|
|
"1. Carefully analyze the objectives and requirements of the workflow_step assigned to you.\n"
|
|
"2. Use the tools assigned to you (if any) or rely on your own knowledge and reasoning to complete the task accurately and efficiently.\n"
|
|
"3. Return the execution results, generated data, or concrete outputs strictly in the ForWorkflow format.\n"
|
|
"Note: Your output should be specific, practical, and directly provide the results requested by the task. Avoid excessive irrelevant pleasantries."
|
|
),
|
|
},
|
|
}
|
|
|
|
# ─── API / 通用消息 ────────────────────────────────────────────────────────
|
|
|
|
_MESSAGES: Dict[str, Dict[str, str]] = {
|
|
"internal_error": {
|
|
"zh": "服务内部错误,请稍后重试",
|
|
"en": "Internal server error, please try again later.",
|
|
},
|
|
"user_not_found": {
|
|
"zh": "用户不存在或已被删除,请重新登录",
|
|
"en": "User does not exist or has been deleted. Please log in again.",
|
|
},
|
|
"provider_not_registered": {
|
|
"zh": "Provider {provider_title} 未注册",
|
|
"en": "Provider {provider_title} is not registered.",
|
|
},
|
|
"model_not_exist": {
|
|
"zh": "模型不存在",
|
|
"en": "Model does not exist.",
|
|
},
|
|
"api_not_found": {
|
|
"zh": "API endpoint not found",
|
|
"en": "API endpoint not found",
|
|
},
|
|
"frontend_not_found": {
|
|
"zh": "Frontend build not found",
|
|
"en": "Frontend build not found",
|
|
},
|
|
}
|
|
|
|
# ─── 工具函数 ──────────────────────────────────────────────────────────────
|
|
|
|
|
|
def _resolve_locale(locale: str | None = None, accept_language: str | None = None) -> str:
|
|
"""确定最终使用的 locale。
|
|
|
|
优先级:显式传入 > Accept-Language 头 > KILOSTAR_LANG 环境变量 > 默认 zh。
|
|
"""
|
|
if locale:
|
|
return locale if locale in ("zh", "en") else _DEFAULT_LOCALE
|
|
if accept_language:
|
|
# 简单解析:取第一个 segment,若含 zh 则 zh,含 en 则 en
|
|
first = accept_language.split(",")[0].split(";")[0].strip().lower()
|
|
if "zh" in first:
|
|
return "zh"
|
|
if "en" in first:
|
|
return "en"
|
|
return _DEFAULT_LOCALE
|
|
|
|
|
|
def t(key: str, locale: str | None = None, accept_language: str | None = None, **kwargs) -> str:
|
|
"""通用消息翻译。
|
|
|
|
Args:
|
|
key: 消息键,如 ``internal_error``。
|
|
locale: 显式指定语言代码(``zh`` / ``en``)。
|
|
accept_language: 前端传来的 ``Accept-Language`` 头内容。
|
|
**kwargs: 模板变量插值。
|
|
|
|
Returns:
|
|
翻译后的字符串;若 key 不存在则返回 key 本身。
|
|
"""
|
|
loc = _resolve_locale(locale, accept_language)
|
|
text = _MESSAGES.get(loc, {}).get(key) or _MESSAGES.get(_DEFAULT_LOCALE, {}).get(key) or key
|
|
return text.format(**kwargs) if kwargs else text
|
|
|
|
|
|
def agent_prompt(
|
|
agent_name: str,
|
|
locale: str | None = None,
|
|
accept_language: str | None = None,
|
|
custom_system_prompt: str | None = None,
|
|
) -> str:
|
|
"""获取指定 Agent 的 system prompt,并追加语言指令。
|
|
|
|
若 ``custom_system_prompt`` 不为空,追加在默认 prompt 和语言指令之后,
|
|
使管理员自定义内容能够覆盖/补充默认行为,同时保留角色定义。
|
|
"""
|
|
loc = _resolve_locale(locale, accept_language)
|
|
prompt = _PROMPTS.get(agent_name, {}).get(loc) or _PROMPTS.get(agent_name, {}).get(_DEFAULT_LOCALE, "")
|
|
lang_instruction = {
|
|
"zh": "\n\n【重要】请始终使用简体中文进行思考和回复。",
|
|
"en": "\n\n[Important] Please always think and reply in English.",
|
|
}.get(loc, "")
|
|
result = prompt + lang_instruction
|
|
if custom_system_prompt and custom_system_prompt.strip():
|
|
result += f"\n\n{custom_system_prompt.strip()}"
|
|
return result
|