M4b:ai_provider 删除手术①-⑥——神识全面接管模型出口

- ① 后端删除 app/ai_provider/(38 文件,含 anthropic/openai 格式、billing、audio、embedding)、services/ai_provider_admin.py、core/config/model_config.py、tests/ai_provider/(21 文件)
- ② 连带退役 application/agent/(旧 Agent 循环/steer/follow-up/确认注册表)、application/skill_executor.py、app/skills/(python skills 孤儿)、endpoints/audio.py、application/imports.py(ProviderManager 消费方);settings 端点收敛为生成偏好
- ③ runs.py 修剪:AgentRunRegistry/steer/follow-up/confirmations 端点退役,保留 list/get/events/cancel/stream;safety 确认改为直接落库裁决(pending→approved/denied)
- ④ 前端删除:models 页、ModelGatewayView、gateway.ts、GatewayPanel(玄关)、ModelGatewayPanel/ModelStrategyForm、audio.ts/useVoiceInput、网关类型与 mock;设置页收敛为外观/语言/通知
- ⑤ 配置收敛:config/models|providers|pricing.example.yaml 归档 shenshi/config/;.env.example 删 provider keys/MODEL_ENDPOINT_POOL/MODEL_CONFIG_PATH,收敛 SHENSHI_*
- ⑥ 验收:rg 审计灵台 Provider SDK import 与 ai_provider 引用归零;后端 528 passed(2 个预存失败经 HEAD 复跑验证与本手术无关)、前端 type-check+201 passed、神识 go vet+test、BFF 4 passed
This commit is contained in:
chenxin committed 2026-08-27 10:02:44 +08:00
1 parent 0d383725b5
commit 462d570751
129 files changed
+81 -15867

No files matched your search

@@ -1,101 +0,0 @@
from unittest.mock import AsyncMock, MagicMock
from app.application.agent.tools import to_ai_provider_tools
from app.application.skill_executor import SkillExecutor
from app.application.tool_runtime.view import RunScopedToolView
from app.modules.skills.manifest import SkillManifest
from app.modules.tool_runtime.definition import ToolResult, ToolSpec
def _spec(name: str) -> ToolSpec:
return ToolSpec(
name=name,
description=f"{name} description",
risk_level="L1",
permission_policy=MagicMock(),
input_schema={
"type": "object",
"properties": {"value": {"type": "string"}},
"required": ["value"],
},
)
async def test_aliases_are_isolated_and_execute_through_base_runtime() -> None:
runtime = MagicMock()
runtime.list_specs.return_value = [_spec("shared_tool")]
runtime.execute = AsyncMock(
return_value=ToolResult(True, 0, "ok", "", 1, False, False, "trace_1")
)
first = RunScopedToolView(runtime)
second = RunScopedToolView(runtime)
assert first.bind_alias("skill:甲/shared_tool", "shared_tool", description_prefix="[甲] ")
assert second.bind_alias("skill:乙/shared_tool", "shared_tool", description_prefix="[乙] ")
first_names = {spec.name for spec in first.list_specs()}
second_names = {spec.name for spec in second.list_specs()}
result = await first.execute(
"skill:甲/shared_tool",
{"value": "x"},
run_id="run_1",
character_id="char_1",
)
assert "skill:甲/shared_tool" in first_names
assert "skill:乙/shared_tool" not in first_names
assert "skill:乙/shared_tool" in second_names
assert "skill:甲/shared_tool" not in second_names
assert result.stdout == "ok"
runtime.execute.assert_awaited_once_with(
"shared_tool",
{"value": "x"},
run_id="run_1",
character_id="char_1",
trace_id=None,
confirmed=False,
context=None,
)
runtime.register.assert_not_called()
runtime.unregister.assert_not_called()
def test_alias_keeps_target_input_schema() -> None:
runtime = MagicMock()
runtime.list_specs.return_value = [_spec("custom_tool")]
view = RunScopedToolView(runtime)
view.bind_alias("skill:研究/custom_tool", "custom_tool")
tools = to_ai_provider_tools(view.list_specs())
alias = next(tool for tool in tools if tool["function"]["name"] == "skill:研究/custom_tool")
assert alias["function"]["parameters"]["required"] == ["value"]
async def test_skill_executor_binds_only_current_run_aliases(
monkeypatch,
) -> None:
manifest = SkillManifest(
name="研究",
description="",
triggers=("研究",),
prompt="研究说明",
allowed_tools=("shared_tool", "missing"),
risk_level="L1",
)
async def load(*_args, **_kwargs):
return [manifest]
monkeypatch.setattr("app.application.skill_executor.load_skill_manifests", load)
runtime = MagicMock()
runtime.list_specs.return_value = [_spec("shared_tool")]
view = RunScopedToolView(runtime)
messages: list[str] = []
await SkillExecutor(view).match_and_activate("请研究", messages, run_id="run_1")
assert messages == ["【研究·能力注入】\n研究说明"]
assert "skill:研究/shared_tool" in view.specs_by_name()
assert "skill:研究/missing" not in view.specs_by_name()
runtime.register.assert_not_called()