From fa3dc76d538820bc47a8bec06f2833e7717a6e8c Mon Sep 17 00:00:00 2001 From: lix-2026 Date: Mon, 25 May 2026 02:55:45 +0800 Subject: [PATCH] refactor: delegate filetree upload fallback --- ...0-browser-runtime-followup-checklist-v1.md | 5 +++ .../mnote-web/browser/filetree-runtime.js | 32 ++++++++++++++++++- rust/crates/mnote-web/src/ssr/pages/layout.rs | 13 ++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/design/03-rust-web/process/3-20-browser-runtime-followup-checklist-v1.md b/design/03-rust-web/process/3-20-browser-runtime-followup-checklist-v1.md index b48c99e1..80c54121 100644 --- a/design/03-rust-web/process/3-20-browser-runtime-followup-checklist-v1.md +++ b/design/03-rust-web/process/3-20-browser-runtime-followup-checklist-v1.md @@ -124,3 +124,8 @@ UI / 浏览器可见项必须有真实浏览器截图或结构化 smoke 证据 - 2026-05-25:Batch E 派发异常并终止:Worker B 任务被重复启动为两个 runner / ACP 进程(`reasonix-2026-05-24T18-25-26-844Z-33ea4d58`、`reasonix-2026-05-24T18-26-04-453Z-5ff62e40`),同一 worktree `/mnt/Data1T/mnote-worktrees/0525-e-worker-b-3-20-conflict-diff-dom` 出现并发写入风险;Codex 已终止相关 Reasonix 进程,未读取到 `final.md`、`result.json`、`process-handoff.md/json`。原始未验证 diff 不直接采纳;后续采纳必须经过 Codex 独立复核、修正和验证。 - 2026-05-25:Batch F 计划继续采用独立 worktree 候选 patch:Worker B 负责把 file tree 上传目标解析的纯 fallback / plan 归一化 helper 外置到 `filetree-runtime.js`;`layout.rs` 仍保留 async preflight 和完整 inline fallback,避免和当前 conflict panel 写集冲突。 - 2026-05-25:Batch F Worker B 异常终止:run `reasonix-2026-05-24T18-39-34-442Z-d9e7ada1` 只产出 `prompt.md` / `memory-recall.json` / `reasonix-transcript.jsonl`,未产出 `final.md`、`result.json`、`process-handoff.md/json`,worktree 无 diff;transcript 停在 `ask_choice`,原因是 worker 误判任务书拼接了 Worker A / Worker B 两个任务并要求人工选择。Codex 已终止 runner / ACP,不采纳该 run。 +- 2026-05-25:Batch G 超限派发并终止:Worker B/C/D 三个 Reasonix runner 同时启动,超过当前 goal 的“每批最多 2 个 worker”;run `reasonix-2026-05-24T18-51-00-477Z-1307a1b4`、`reasonix-2026-05-24T18-51-00-504Z-2304f570`、`reasonix-2026-05-24T18-51-00-541Z-17d61f43` 均只有 `prompt.md` / `memory-recall.json` / `reasonix-transcript.jsonl`,无 handoff,worktree 无 diff;Codex 已终止 runner / ACP,不采纳该批。 +- 2026-05-25:Codex 主控完成 filetree upload target fallback 小切片:`filetree-runtime.js` 新增并导出 `fileTreeUploadTargetFallback(detail, deps)`,承接同步 fallback / plan 归一化;`layout.rs` 的 `fallbackFileTreeUploadTarget` 优先委托 runtime,仍保留完整 inline fallback;async preflight、后端归属判定、`uploadFileToMediaAsset`、`uploadFilesWithResolvedTarget` 不迁。 + - 修改:`rust/crates/mnote-web/browser/filetree-runtime.js`、`rust/crates/mnote-web/src/ssr/pages/layout.rs`。 + - 已验证:`node --check rust/crates/mnote-web/browser/filetree-runtime.js`、`cargo fmt --manifest-path rust/Cargo.toml --all --check`、`cargo check --manifest-path rust/Cargo.toml -p mnote-web`、`cargo test --manifest-path rust/Cargo.toml -p mnote-web filetree -- --test-threads=1`、`cargo test --manifest-path rust/Cargo.toml -p mnote-web local_upload_runtime_contains_editor_upload_context_helpers -- --test-threads=1`、`NODE_PATH=/mnt/Data1T/mnote/node_modules node scripts/task479-local-folder-markdown-resource-lifecycle-smoke.js`。 + - 未完成:async preflight、`refreshLocalFolderSidebarSnapshot` / `appendUploadedAssetRow`、conflict action helpers、secondary pane conflict smoke 仍未迁出或覆盖。 diff --git a/rust/crates/mnote-web/browser/filetree-runtime.js b/rust/crates/mnote-web/browser/filetree-runtime.js index a0de879b..dcddc252 100644 --- a/rust/crates/mnote-web/browser/filetree-runtime.js +++ b/rust/crates/mnote-web/browser/filetree-runtime.js @@ -120,6 +120,35 @@ function fileTreeChildCount(documentId, deps) { return children.length; } +function fileTreeUploadTargetFallback(detail, deps) { + detail = detail || {}; + deps = deps || {}; + var resolveWorkspaceId = typeof deps.resolveWorkspaceId === 'function' ? deps.resolveWorkspaceId : function() { return ''; }; + var currentDocumentId = typeof deps.currentDocumentId === 'function' ? deps.currentDocumentId : function() { return ''; }; + var workspaceId = String(detail.workspaceId || resolveWorkspaceId(document.body) || '').trim(); + var documentId = String(detail.documentId || currentDocumentId() || '').trim(); + if (Object.prototype.hasOwnProperty.call(detail, 'targetRelativePath')) { + return { + workspaceId: workspaceId, + targetDocumentId: documentId, + targetMindmapId: null, + targetSubPath: null, + targetRelativePath: String(detail.targetRelativePath || ''), + uploadIntent: String(detail.uploadIntent || 'filetree.folder.drop') + }; + } + if (!workspaceId || !documentId) { + throw new Error('请选择一个目标页面后再拖入文件'); + } + return { + workspaceId: workspaceId, + targetDocumentId: documentId, + targetMindmapId: null, + targetSubPath: null, + uploadIntent: String(detail.uploadIntent || 'editor.markdown.attach') + }; +} + window.__mnoteFileTreeRuntime = { fileTreeRowKind: fileTreeRowKind, fileTreeRowDocumentId: fileTreeRowDocumentId, @@ -131,5 +160,6 @@ window.__mnoteFileTreeRuntime = { isFileTreeDownloadableRow: isFileTreeDownloadableRow, fileTreeAssetDownloadDetail: fileTreeAssetDownloadDetail, fileTreeRowsByRowIds: fileTreeRowsByRowIds, - fileTreeChildCount: fileTreeChildCount + fileTreeChildCount: fileTreeChildCount, + fileTreeUploadTargetFallback: fileTreeUploadTargetFallback }; diff --git a/rust/crates/mnote-web/src/ssr/pages/layout.rs b/rust/crates/mnote-web/src/ssr/pages/layout.rs index 483fa86f..d943aec6 100644 --- a/rust/crates/mnote-web/src/ssr/pages/layout.rs +++ b/rust/crates/mnote-web/src/ssr/pages/layout.rs @@ -3093,6 +3093,13 @@ const SIDEBAR_TREE_JS: &str = r##" } function fallbackFileTreeUploadTarget(detail) { + var runtimeFn = fileTreeRuntimeFunction('fileTreeUploadTargetFallback'); + if (runtimeFn) { + return runtimeFn(detail || {}, { + resolveWorkspaceId: resolveWorkspaceId, + currentDocumentId: currentDocumentId + }); + } var workspaceId = String(detail && detail.workspaceId || resolveWorkspaceId(document.body) || '').trim(); var documentId = String(detail && detail.documentId || currentDocumentId() || '').trim(); if (detail && Object.prototype.hasOwnProperty.call(detail, 'targetRelativePath')) { @@ -11031,6 +11038,7 @@ mod tests { assert!(SIDEBAR_TREE_JS.contains("fileTreeRuntimeFunction('fileTreeAssetDownloadDetail')")); assert!(SIDEBAR_TREE_JS.contains("fileTreeRuntimeFunction('fileTreeRowsByRowIds')")); assert!(SIDEBAR_TREE_JS.contains("fileTreeRuntimeFunction('fileTreeChildCount')")); + assert!(SIDEBAR_TREE_JS.contains("fileTreeRuntimeFunction('fileTreeUploadTargetFallback')")); let document_id_body = js_function_body(SIDEBAR_TREE_JS, "fileTreeRowDocumentId"); assert!( document_id_body.contains("data-document-id") @@ -11050,6 +11058,11 @@ mod tests { assert!(FILETREE_RUNTIME_JS.contains("function fileTreeAssetDownloadDetail")); assert!(FILETREE_RUNTIME_JS.contains("function fileTreeRowsByRowIds")); assert!(FILETREE_RUNTIME_JS.contains("function fileTreeChildCount")); + assert!(FILETREE_RUNTIME_JS.contains("function fileTreeUploadTargetFallback")); + assert!(FILETREE_RUNTIME_JS + .contains("uploadIntent: String(detail.uploadIntent || 'filetree.folder.drop')")); + assert!(FILETREE_RUNTIME_JS + .contains("uploadIntent: String(detail.uploadIntent || 'editor.markdown.attach')")); } #[test]