Skip to content

feat: fork on a user prompt rewinds and refills the composer - #47

Merged
shaohaozhi286 merged 4 commits into
masterfrom
feat/fork-user-prompt-to-composer
Sep 9, 2026
Merged

feat: fork on a user prompt rewinds and refills the composer#47
shaohaozhi286 merged 4 commits into
masterfrom
feat/fork-user-prompt-to-composer

Conversation

@LIUXIN557

Copy link
Copy Markdown
Collaborator

背景

桌面版/网页版对会话做分叉时,若选中的是一条用户提示词,原先会把该提示词本身也复制进新会话。期望行为是:分叉点落在该提示词之前(即上一次 agent 回复处),并把提示词原文回填到输入框,供用户修改后重发。

行为

  • 分叉锚点:从点击的用户消息向前扫描,跳过非对话记录(file checkpoint / turn timing / turn net diff / meta),遇到第一条真实消息停下;遇到 tool_call 不在中途截断,保证 tool_call / tool_result 成对。
  • 用户消息分叉:截断到锚点之前,把提示词原文回填输入框(多模态消息取 text 部分,跳过附件)。
  • assistant 消息分叉:行为保持原样。
  • 回填后原样发送仍然允许——分叉出的是独立会话,重放同一提示词不会影响原会话。
  • toast 文案简化为「已创建分支会话」。

改动

  • 后端 session_rewind:新增 resolve_fork_anchor_indexfork_restored_prompt_text;fork 路由新增返回 restored_prompt / fork_anchor_role
  • 前端 ChatView.jsxforkAndSwitch:切换会话前回填 composer 并保留,避免被会话切换清空。
  • i18n:登记新文案(zh-CN + en-US)。
  • 附带打包脚本 scripts/macos_create_portable_zip.sh 与配套 skill(含三道防呆,防止把旧前端静默嵌进包里)。

验证

  • C++ 单测 SessionRewind + MessagePayload 21/21
  • Fork HTTP 用例 3/3
  • 前端 i18n 审计通过(static-copy compiler coverage)
  • 便携包已构建,grep 二进制确认前后端 fork 逻辑均在包内

备注

本 PR 同时包含一个与功能无关的 chore 提交(macOS 便携包脚本 + skill)。如需拆成独立 PR 我可以另行处理。

Forking at a user prompt used to copy that prompt into the new session
history verbatim. It now rewinds to the state just before the prompt and
returns the prompt text as restored_prompt so the UI can refill the
composer for the user to edit and resend. Forking at an assistant message
keeps the previous behaviour unchanged.

Backend: resolve_fork_anchor_index scans back past meta/checkpoint/
timing/net-diff records and refuses to stop on an assistant message with
unanswered tool calls, so the forked prefix never ends mid-tool-call.
fork_restored_prompt_text falls back to joining text parts when a
multimodal user message carries no plain content.

Frontend: forkAndSwitch sets the composer-preserve flag before switching
sessions, then refills from restored_prompt.

Tests: unit tests for anchor resolution and prompt extraction, plus HTTP
route tests asserting restored_prompt for user targets and its absence
for assistant targets. OpenSpec change fork-user-prompt-to-composer.
…guards

- scripts/macos_create_portable_zip.sh: builds a self-contained .app + TUI
  + share/acecode tree via cmake install; three guards prevent silently
  shipping stale embedded web UI (frontend newer than embedded assets ->
  auto reconfigure+rebuild; grep binary to confirm UI embedded).
- macos-portable-package skill mirrored into .claude/.acecode/.agents/.codex
  skills/ so all agent toolchains can invoke it.
Shortens the restored-prompt toast from 已分叉,提示词已回填输入框,可修改后重发
to just 已创建分支会话; the composer refill behaviour is unchanged.
Registers the new copy in the i18n source catalog (zh-CN + en-US).
…pt-to-composer

# Conflicts:
#	web/scripts/i18n-en-overrides.mjs

@shaohaozhi286 shaohaozhi286 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

发现原会话草稿覆盖风险,以及附带 macOS 打包脚本的 3 个可定位问题,建议修复后再合并;也可将打包改动拆成独立 PR。验证:本地 pnpm test、pnpm build 通过;CI 中新增 fork anchor/prompt 测试及相关 Fork HTTP 测试通过。用现有草稿 cleanup 回调复现了旧 session ID 被写入 fork 回填文本。CI 的两个终端/工具链失败在主干 run 34356121713 同样存在,不认定为本 PR 回归。macOS 打包问题依据脚本控制流审查,本机未执行 macOS 实机打包。

const restoredPrompt = forkRestoredPrompt(r);
if (restoredPrompt) {
preserveComposerInputOnSessionChangeRef.current = true;
setComposerValue(restoredPrompt);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 在切换会话前保护原会话尚未保存的草稿。若用户已输入新草稿且 350ms 自动保存尚未完成,composerDirtyRef 为 true。这里先将 composerValue 改为历史提示词,再切换会话;新 render 在第 884 行更新 composerValueRef,而旧会话 cleanup(1743-1751)仍捕获旧 sid,并将该 ref 当前值保存到旧会话,导致原草稿被历史提示词覆盖。提取现有 cleanup 回调按此顺序执行,确实得到 persistDraftValue(original-session, ..., restored-prompt)。建议先用原文本保存并解除旧会话 dirty 状态,或使用会话级快照/pending fork payload,在目标会话完成切换后回填;补充“旧会话有未保存草稿时分叉,返回原会话草稿保持”的回归测试。

-DBUILD_TESTING=OFF -DACECODE_BUILD_DESKTOP=ON \
-DVCPKG_MANIFEST_FEATURES=tests -DVCPKG_MANIFEST_INSTALL=OFF
echo "== rebuilding acecode-desktop with fresh embedded assets =="
"$CMAKE_BIN" --build "$build_dir" --target acecode-desktop

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] 无论前端是否变化,都应执行一次增量 C++ 构建。当前唯一的 cmake --build 放在 needs_reconfigure 分支里,而该条件只检查 web/dist/index.html 和 embed marker。首次打包后,只修改或拉取 C++ 代码再执行脚本,条件为 false,程序会直接复制旧 acecode/ACECode.app 并成功通过 provider-logos 检查,产物不包含本次后端修复。建议只将 configure 放在条件内,把 --build 移到条件外;增加前端不变、后端变化时仍执行 build 的脚本回归验证。

"$CMAKE_BIN" -S "$repo_root" -B "$build_dir" -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE="$HOME/vcpkg/scripts/buildsystems/vcpkg.cmake" \
-DVCPKG_TARGET_TRIPLET=x64-osx \

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] --arch arm64 必须同步选择 vcpkg triplet 和构建缓存。此处无论参数均强制 x64-osx,配合 CMAKE_OSX_ARCHITECTURES=arm64 会混用 x86_64 依赖;而默认 build 目录始终是 macos-x64-release,前端哈希匹配时甚至不会重新配置,会把旧 x64 二进制命名为 arm64 包。建议从校验后的 arch 推导 x64-osx/arm64-osx 和独立 build 目录,将架构/缓存匹配作为配置条件,并在归档前验证实际二进制架构。

echo "== zipping with ditto =="
rm -f "$output_path"
( cd "$repo_root/dist" && /usr/bin/ditto -c -k --keepParent --sequesterRsrc \
"$package_name" "$(basename "$output_path")" )

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] 归档应写入 --output 指定的完整路径。当前在 repo/dist 中调用 ditto,但仅传 basename(output_path),所以 --output /tmp/custom.zip 实际写到 repo/dist/custom.zip;随后却用 /tmp/custom.zip 解压,导致失败,而且前面的 rm -f 已删除用户指定位置的旧文件。建议先将 output_path 规范化为绝对路径并创建父目录,再把完整路径传给 ditto,验证和报告使用同一条路径。

@shaohaozhi286
shaohaozhi286 merged commit c7d9e99 into master Sep 9, 2026
1 check failed
@shaohaozhi286

Copy link
Copy Markdown
Collaborator

已随集成分支合并到 master,修复提交:2b68a67235740966257a51be353f0f098acf03c6。回填改为目标会话激活后消费,原会话未保存草稿不会被覆盖。打包脚本始终增量构建,隔离并校验架构,且遵守完整输出路径。完整 pnpm test/build 通过,新增草稿生命周期测试及 4 项模拟 macOS 工具的打包回归通过。本机未做原生 macOS 编译或 GUI 启动;C++ fork 测试沿用本 PR CI 验证,已有两个 Linux 基线失败单独记录。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants