release: OpenNexus 0.5.1-alpha

This commit is contained in:
2026-09-18 00:56:54 +08:00
parent f7d441bd92
commit 01ceae6fc6
32 changed files with 496 additions and 33 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ def get_settings() -> Settings:
data_dir = Path(os.getenv("APP_DATA_DIR", str(BACKEND_DIR / "data")))
return Settings(
name=os.getenv("APP_NAME", "OpenNexus AI Core"),
version=os.getenv("APP_VERSION", "0.5.0"),
version=os.getenv("APP_VERSION", "0.5.1-alpha"),
environment=os.getenv("APP_ENVIRONMENT", "development"),
host=os.getenv("APP_HOST", "127.0.0.1"),
port=int(os.getenv("APP_PORT", "8000")),
+15
View File
@@ -194,6 +194,21 @@ MIGRATIONS: list[str] = [
CREATE INDEX IF NOT EXISTS idx_workspace_asset_links_note
ON workspace_asset_links(note_id, note_path);
""",
# v14:桌面端 Markdown 先由 Rust Host 落盘,notes 只是可重建的搜索投影。
# 媒体产物不能依赖投影已同步,否则文件创建成功后关联会因外键失败。
"""
CREATE TABLE media_notes_v14 (
job_id TEXT NOT NULL REFERENCES media_jobs(job_id) ON DELETE CASCADE,
revision INTEGER NOT NULL,
options_hash TEXT NOT NULL,
note_id TEXT NOT NULL,
PRIMARY KEY(job_id, revision, options_hash)
);
INSERT INTO media_notes_v14 (job_id, revision, options_hash, note_id)
SELECT job_id, revision, options_hash, note_id FROM media_notes;
DROP TABLE media_notes;
ALTER TABLE media_notes_v14 RENAME TO media_notes;
""",
]
+24 -10
View File
@@ -187,11 +187,9 @@ async def create_transcript_artifacts(job_id, options):
return {"transcript": transcript_note, "knowledge_note": knowledge_note}
markdown = await _knowledge_markdown(job, options.provider_id, options.model, knowledge_title)
note_title = f"{knowledge_title} · {job_id[-8:]}-r{job.revision}-{signature[-6:]}"
knowledge_note = await note_service.create_note(
title=note_title,
markdown=markdown,
folder=options.folder,
tags=["课程笔记", "知识点"],
marker = markdown.splitlines()[0]
knowledge_note = await _create_note(
note_title, markdown, options, marker, tags=["课程笔记", "知识点"]
)
with closing(connect()) as conn, transaction(conn):
conn.execute("INSERT OR IGNORE INTO media_notes VALUES (?,?,?,?)",
@@ -199,14 +197,30 @@ async def create_transcript_artifacts(job_id, options):
return {"transcript": transcript_note, "knowledge_note": knowledge_note}
async def _create_note(title, markdown, options, marker):
async def _create_note(title, markdown, options, marker, *, tags=None):
try:
note = await note_service.create_note(title=title, markdown=markdown, folder=options.folder, tags=["转写"])
note = await note_service.create_note(
title=title, markdown=markdown, folder=options.folder, tags=tags or ["转写"]
)
except ApiError as exc:
if exc.code != "RESOURCE_CONFLICT" or "note_id" not in exc.details:
if exc.code == "RESOURCE_CONFLICT" and "note_id" in exc.details:
note = await note_service.get_note(exc.details["note_id"])
elif exc.code == "REVISION_CONFLICT":
# Rust Host 已完成写入、但 Core 尚未来得及保存关联时,重试会报告路径冲突。
# 只恢复标题和不可伪造的任务 marker 都匹配的文件,避免误认用户同名笔记。
summaries, _ = note_service.list_notes(
limit=1000, offset=0, folder=options.folder, tag=None
)
note = None
for summary in summaries:
if summary.title != title:
continue
candidate = await note_service.get_note(summary.note_id)
if candidate is not None and marker in candidate.markdown:
note = candidate
break
else:
raise
# 恢复笔记创建成功后、关联任务前发生的崩溃。
note = await note_service.get_note(exc.details["note_id"])
if note is None or marker not in note.markdown:
raise
return note