release: OpenNexus 0.5.1-alpha
This commit is contained in:
@@ -59,8 +59,78 @@ def test_zip_install_real_mcp_tool_command_and_skill(tmp_path):
|
||||
config = runtime.skills.build_agent_configuration('note-reviewer', [ModelCapability.chat, ModelCapability.tool_calling])
|
||||
assert 'notes.read' in config.allowed_tools
|
||||
assert '不得改变用户指定的检查范围' in config.system_prompt
|
||||
rewrite_skill = install_zip((output / 'course-note-rewriter-1.0.0.zip').read_bytes(), 'skill', tmp_path / 'installed', runtime.skills.install)
|
||||
assert not rewrite_skill.missing_dependencies
|
||||
assert runtime.skills.enable('course-note-rewriter').status == 'ready'
|
||||
rewrite_config = runtime.skills.build_agent_configuration('course-note-rewriter', [ModelCapability.chat, ModelCapability.tool_calling])
|
||||
assert 'notes.create' in rewrite_config.allowed_tools
|
||||
assert 'markdown-workbench.inspect_markdown' in rewrite_config.allowed_tools
|
||||
assert '三道自测题' in rewrite_config.system_prompt
|
||||
runtime.plugins.disable('markdown-workbench')
|
||||
assert runtime.skills.get('note-reviewer').status == 'dependency_missing'
|
||||
assert runtime.skills.get('course-note-rewriter').status == 'dependency_missing'
|
||||
try:
|
||||
asyncio.run(run())
|
||||
finally:
|
||||
runtime.plugins.shutdown()
|
||||
|
||||
|
||||
def test_study_plan_plugin_and_adaptive_skill_are_real_local_packages(tmp_path):
|
||||
builder = load(ROOT / 'build_packages.py')
|
||||
output = tmp_path / 'dist'
|
||||
catalog = builder.build(output)
|
||||
assert [item['id'] for item in catalog['packages'] if item['kind'] == 'plugin'] == [
|
||||
'markdown-workbench', 'study-plan-kit'
|
||||
]
|
||||
assert {'course-note-rewriter', 'adaptive-study-coach'} <= {
|
||||
item['id'] for item in catalog['packages'] if item['kind'] == 'skill'
|
||||
}
|
||||
runtime = build_container()
|
||||
|
||||
async def run():
|
||||
plugin = install_zip(
|
||||
(output / 'study-plan-kit-1.0.0.zip').read_bytes(),
|
||||
'plugin',
|
||||
tmp_path / 'installed',
|
||||
runtime.plugins.install,
|
||||
)
|
||||
assert not plugin.enabled
|
||||
skill = install_zip(
|
||||
(output / 'adaptive-study-coach-1.0.0.zip').read_bytes(),
|
||||
'skill',
|
||||
tmp_path / 'installed',
|
||||
runtime.skills.install,
|
||||
)
|
||||
assert 'study-plan-kit.build_sprint' in skill.missing_dependencies
|
||||
assert runtime.plugins.enable('study-plan-kit').status == 'ready'
|
||||
result = await runtime.tools.execute(
|
||||
ToolCall(
|
||||
tool_call_id='study-plan-test',
|
||||
name='study-plan-kit.build_sprint',
|
||||
arguments={
|
||||
'topic': '三数和与头尾双指针',
|
||||
'days': 7,
|
||||
'daily_minutes': 45,
|
||||
'confidence': 2,
|
||||
'weak_points': '去重和指针移动条件',
|
||||
},
|
||||
),
|
||||
ToolExecutionContext(run_id='study-plan-test'),
|
||||
)
|
||||
assert result.success, result.error_message
|
||||
assert result.output['constraints']['total_minutes'] == 315
|
||||
assert len(result.output['schedule']) == 7
|
||||
assert sum(result.output['phases'].values()) == 7
|
||||
assert result.output['constraints']['weak_points'] == '去重和指针移动条件'
|
||||
assert runtime.skills.enable('adaptive-study-coach').status == 'ready'
|
||||
config = runtime.skills.build_agent_configuration(
|
||||
'adaptive-study-coach', [ModelCapability.chat, ModelCapability.tool_calling]
|
||||
)
|
||||
assert 'tasks.create' in config.allowed_tools
|
||||
assert '严格保持工具返回的总分钟数' in config.system_prompt
|
||||
runtime.plugins.disable('study-plan-kit')
|
||||
assert runtime.skills.get('adaptive-study-coach').status == 'dependency_missing'
|
||||
|
||||
try:
|
||||
asyncio.run(run())
|
||||
finally:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""无需模型下载的耐久性、取消和乐观编辑。"""
|
||||
import asyncio
|
||||
from contextlib import closing
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
@@ -116,6 +117,38 @@ def test_terminology_export_and_privacy_cleanup():
|
||||
assert client.get('/api/media/attachments/lecture.txt').status_code == 404
|
||||
|
||||
|
||||
def test_media_note_links_do_not_depend_on_rebuildable_note_projection():
|
||||
with closing(connect()) as conn:
|
||||
foreign_tables = {row[2] for row in conn.execute("PRAGMA foreign_key_list(media_notes)")}
|
||||
assert foreign_tables == {"media_jobs"}
|
||||
|
||||
|
||||
def test_desktop_revision_conflict_recovers_marker_matched_note(monkeypatch):
|
||||
from app.services import note_service
|
||||
from app.services.media_notes import _create_note
|
||||
|
||||
marker = "<!-- transcription:job:1:hash -->"
|
||||
recovered = SimpleNamespace(note_id="stable-note", title="Generated", markdown=f"{marker}\nbody")
|
||||
|
||||
async def conflict(**_kwargs):
|
||||
raise ApiError(409, "REVISION_CONFLICT", "already written")
|
||||
|
||||
monkeypatch.setattr(note_service, "create_note", conflict)
|
||||
monkeypatch.setattr(
|
||||
note_service, "list_notes",
|
||||
lambda **_kwargs: ([SimpleNamespace(note_id="stable-note", title="Generated")], 1),
|
||||
)
|
||||
|
||||
async def get_note(note_id):
|
||||
return recovered if note_id == "stable-note" else None
|
||||
|
||||
monkeypatch.setattr(note_service, "get_note", get_note)
|
||||
result = asyncio.run(_create_note(
|
||||
"Generated", recovered.markdown, SimpleNamespace(folder=""), marker
|
||||
))
|
||||
assert result is recovered
|
||||
|
||||
|
||||
def test_local_only_export_and_rebuild_keep_local_embedding_policy(monkeypatch):
|
||||
from types import SimpleNamespace
|
||||
from app.contracts import TranscriptNoteRequest, IndexRebuildRequest
|
||||
|
||||
Reference in New Issue
Block a user