Skip to content

feat(settings): 支持全局与项目提示词配置 - #587

Merged
su-fen merged 8 commits into
Stack-Cairn:mainfrom
yovinchen:feat/prompt-template-scopes-271
Aug 21, 2026
Merged

feat(settings): 支持全局与项目提示词配置#587
su-fen merged 8 commits into
Stack-Cairn:mainfrom
yovinchen:feat/prompt-template-scopes-271

Conversation

@yovinchen

@yovinchen yovinchen commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

概述

为提示词配置增加清晰的全局与项目两层作用域,同时保留现有全局模板单选互斥行为。

主要改动

  • 全局提示词模板仍然最多启用一个;启用新模板时自动停用当前模板
  • 每个项目可配置一份项目提示词
  • 项目提示词支持两种策略:
    • 拼接:先应用当前全局提示词,再追加项目提示词
    • 覆盖:该项目仅使用项目提示词
  • 项目提示词为空时继续使用当前全局提示词
  • 将原“全局提示词”设置页调整为“提示词模板”,统一展示全局模板与项目提示词
  • 项目提示词卡片提供预览与编辑操作;预览按“全局提示词 / 项目提示词”标识区分最终组成
  • 项目右键菜单不增加独立提示词入口;提示词编辑位于现有“配置”弹窗的“项目提示词”页签
  • 普通发送、Text 模式、手动压缩和 Auto Prompt/Cron 使用同一套有效提示词解析规则
  • Text 模式单独解析 conversation workspace,避免因工具工作目录为空而错误回退到全局提示词

设计取舍

Issue 最初建议同时启用多个全局模板。本实现没有改变现有全局单选模型,而是通过“一个全局模板 + 一份项目提示词”的分层方式提供组合能力,降低全局模板顺序和冲突管理的复杂度。

界面预览

提示词模板设置 全局提示词模板 项目提示词配置 项目提示词编辑 最终生效提示词预览

验证

  • pnpm -w run check:fast:12/12 通过
  • Shared UI TypeScript 检查通过
  • Desktop GUI 与 Gateway WebUI 构建通过
  • Tauri Rust check 通过
  • Biome lint 通过
  • Gateway golangci-lint 与 Go tests 通过

Closes #271

@yovinchen
yovinchen marked this pull request as ready for review August 21, 2026 18:18

@su-fen su-fen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

审核结论

建议先修再合。CI 已绿、也能自动合并,分层模型和空闲直发路径是对的,但 Text 模式排队发送会把这次要修的问题重新引进来。

必须修

[P2] 空的 workdirOverride 被当成会话工作区

resolveConversationPromptWorkdir 只要看到 workdirOverride !== undefined 就直接返回,包括空串。排队链路在 Text 模式下会把 workdir 写成 "",再作为 workdirOverride 传进发送函数。

结果是「上一条还在跑、用户接着发下一条」时:

  1. 项目提示词失效,只剩全局模板
  2. historyCwd 变成 undefined,会话 cwd 被写成 NULL,对话从项目里拆出去
  3. 运行时 workdir 被清掉,后面几轮也解析不到项目提示词

这正好打到 PR 自己写的目标:Text 模式要单独解析 conversation workspace,避免工具工作目录为空时退回全局提示词。空闲直发没有 override,所以能过;一进队列,空的工具工作目录又漏回提示词解析。覆盖策略为 replace 时更明显。

建议二选一:

  • 空覆盖视为未指定,回落到 persistedWorkdir / runtimeWorkdir
  • 排队时 Text 模式不要传 workdirOverride

不要把项目路径写进 Text 模式的 workdirOverride,否则工具层会错误拿到工作目录。现有测试只覆盖了「没有 override」,请补一条 workdirOverride: "" 且会话已有 cwd 的用例。

其余看起来没问题

  • resolveEffectivePromptSettings 的 append / replace / 空项目回退全局,语义清楚,也有单测
  • 项目提示词挂在现有 workspaceResourceSettings 上,更新时保留 Skill / MCP;inherit 墓碑和溢出淘汰也把「仅有项目提示词」的条目算成活跃
  • 普通发送、Cron、当前会话手动压缩都走同一套解析
  • 设置页和项目配置弹窗的入口与文案一致

残留说明(不挡这次,但建议知道)

  • 后台手动压缩仍只用全局提示词。input.workdir 其实有,但代码按「跨会话拿不到工作区」直接返回了。这是原有限制,不是回归。
  • Auto Prompt / 发送路径的测试大多是源码字符串匹配,没有覆盖排队、Gateway 入队、覆盖策略下的真实组装。
  • PR 用 Closes #271,但 #271 要的是「同时启用多个全局模板」。实现改成了「全局仍单选 + 每项目一份提示词」,说明里写了取舍。合入前建议确认要不要关 #271,或者改成关联而不关闭。

Comment on lines 33 to 36
if (explicitWorkdir !== undefined) {
return explicitWorkdir.trim();
}
if (!params.isAgentMode) {
return "";
}
return (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[P2] 空字符串 override 不应覆盖会话工作区

排队链路在 Text 模式会把 workdir 写成 "",再作为 workdirOverride 传入。这里 explicitWorkdir !== undefined 对空串也成立,于是直接返回 "",丢掉 persistedWorkdir / runtimeWorkdir

空闲直发没有 override,项目提示词能生效;一旦上一条还在跑、用户接着发下一条,就会:

  1. 项目提示词失效,只剩全局模板
  2. historyCwd 变成 undefined,把会话 cwd 写空
  3. 运行时 workdir 被清掉,后续轮次也解析不到项目提示词

这和本 PR「Text 模式单独解析 conversation workspace」的目标相反。空覆盖应视为未指定并回落到会话 cwd;不要把项目路径写进 Text 模式的 workdirOverride,否则工具层会错误拿到工作目录。请补一条 workdirOverride: "" 且会话已有 cwd 的测试。

Comment on lines +365 to +375
const workdirResolution = {
isAgentMode: effectiveIsAgentMode,
workdirOverride: overrides?.workdirOverride,
gatewayWorkdirOverride: gatewayBridgeRequest?.workdirOverride,
persistedWorkdir: sidebarStore.peek(conversationId)?.cwd,
runtimeWorkdir: runtimeEntry?.workdir,
globalWorkdir: settings.system.workdir,
});
};
const effectiveWorkdir = resolveEffectiveConversationWorkdir(workdirResolution);
const promptWorkdir = resolveConversationPromptWorkdir(workdirResolution);
const effectiveAgentPrompt = resolveEffectivePromptSettings(settings, promptWorkdir).prompt;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

这里把同一份 workdirResolution 同时交给工具工作目录和提示词工作目录。队列传入的 Text 模式 workdirOverride: "" 会让 promptWorkdir 变成空串,随后 historyCwd 也被写成 undefined

resolveEffectiveConversationWorkdir 在 Text 模式返回空是对的(工具不该有工作目录);resolveConversationPromptWorkdir 不应把这个空覆盖当成「会话不属于任何项目」。

@yovinchen
yovinchen requested a review from su-fen August 21, 2026 19:10
@su-fen
su-fen merged commit 29c9f1b into Stack-Cairn:main Aug 21, 2026
9 checks passed
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.

关于 设置 > 全局提示词 的一点点建议

2 participants