Repository navigation
feat: 提示词增强与附件在 prompt 中的表达规范 - #7
Merged
7836246 merged 19 commits intoSep 26, 2026
Merged
Conversation
.kcodeignore 同步 .gitignore 的排除规则,供本地工具复用;docs/prompt-enhance.md 记录提示词增强功能的完整实现规范,作为后续实现的唯一依据。
新增 promptEnhance 设置(改写模式 / 上下文参考 / 结构化覆盖放开 / 模型通道 / 推理强度),
以及三档改写模板和不依赖 React 的纯函数:占位符拼装、结构化内容闸、还原闸、
活动 run 跟踪、设置补齐与通道解析,附 node:test 单测并登记进 CI 的 Focused tests。
拼装一次性扫模板替换占位符:顺序 replaceAll 会让草稿正文里的 {input} 字样被二次改写,
草稿含 $& / $' 时也必须走函数式 replacer。
run 跟踪把「当前是否有活动 run」与「单调递增的 runId」拆开:用墓碑占位活动 run 时,
取消后的下一次点击会被继续判成取消,按钮再也发不出请求,且迟到响应永远清不掉墓碑。
该故障在当前实现里出现过,所以把这段逻辑抽成纯模块并留下回归测试。
schema 注释点明写回形状:ISettingService.update 只合并外层字段,嵌套对象是整体替换,
而 patch schema 的 .partial() 仍会补齐内层默认值——因此必须提交完整 promptEnhance
对象,只交单个字段会被默认值重置掉其它选择。
工具条新增增强 / 还原 / 设置三个入口:点增强用模型改写草稿并原地替换,绝不自动发送; 改写前原文存为一级还原点,草稿被手改后「还原」被拒并说明原因。请求级 60s 超时, 进行中再点即取消,迟到响应按 runId 丢弃;写入异常或读回不一致都写回原文,不留半截文本。 设置页新增「提示词增强」分区(分组 basics),管理改写模式、上下文轮数与开关、 含附件/引用草稿的覆盖放开、独立模型通道及推理强度,改动即写即生效并可恢复默认; 模式与档位选项直接复用共享常量,不在分区里重写一份字面量。写回是「读当前设置 + 完整对象」, 因此保存期间所有控件(含分段控件)禁用,否则连续切两项会用尚未回刷的旧值覆盖前一次选择。 工具条「设置」入口经设置导航意图直达该分区。 composer 用固定 key 跨 session 复用,因此 scope 变化或草稿被清空(发送成功)时主动作废 在途请求并清还原点,避免新会话继承上一个草稿的按钮状态、或留下点了必然被拒的「还原」。 结构化内容闸按规范复用 parseMentionMarkdown,会把 $技能 / /命令 / 路径这类行内 token 一并判为结构化内容;提示语按实际影响逐项说明,需要时由设置放开。 旧 chat.promptEnhance.* 文案无任何引用(属于更早的直连通道方案),改为 chat.toolbar.promptEnhance.* / settings.promptEnhance.*,避免同一功能两套命名。
用户点「增强提示词」必现失败:`params.signal?.addEventListener is not a
function`。
根因:Renderer 经 ProxyChannel 调 Host 服务,实参在
packages/rpc/src/serialization.ts 里对普通对象走 JSON.stringify fallback,
AbortSignal 没有可枚举字段,到 Host 侧变成 `{}`(truthy),服务里
`params.signal?.addEventListener` 直接抛错。(已用探针复现同一条错误串。)
修法:跨进程不再传 AbortSignal,改用可序列化的 operationId —— CLI 早就按
`workspace/generateText` 的 operationId 登记 AbortController,
`workspace/cancelGenerateText` 按 id 触发,本次只把这条既有能力接到服务面:
- shared:导出 KCodeWorkspaceCancelGenerateTextResult。
- services:generateWorkspaceText 优先用调用方带来的 operationId(缺省时才按
signal 自造 uuid);新增 cancelWorkspaceGenerateText 控制面方法,只对已存在的
活跃 workspace client 发取消(不为一条取消拉起 Agent 进程),超时 5s。
- UI:去掉 AbortController,新增 operationId/request 两个纯模块;取消句柄在发起
时固化(operationId + 发起时的 workspace target),由单个 ref 持有,作废或正常
结束时释放,避免 scope 变化后按新 target 把取消打到另一台 Host。
- 测试:新增请求参数不含 signal(回归护栏,经 JSON 序列化往返校验)、target 由
同一函数产出、operationId 唯一等用例。
未验证:真实模型链路上的取消效果需要 provider 凭据,未跑;改动落在 Host 与 Agent
两侧,需重启 `pnpm dev:desktop` 才生效。
用户点增强报 `maxOutputTokens is outside the model option range`,但模型配置里的 上限本身没问题——是请求根本没带预算。 根因:`workspace/generateText` 的模型校验(adapters/src/model/model.ts 的 validateOptions)要求请求合并后的 maxOutputTokens 必须有值且在模型 optionSpecs.maxOutputTokens.max 之内,缺值与越界用的是同一条错误。输出预算属于 单次请求,ModelFactory 刻意不绑定它,git 提交消息那条路靠 auxiliaryModelOptions 兜底,而提示词增强是这个通用入口的第一个调用方,于是漏了。 同一份模型配置还决定档位:Registry 会直接拒「selection 缺 reasoningLevel」与 「档位不在模型 values 内」。原先「设置成 default 就不下发档位」等于每次都被拒。 改法(都在 UI 侧解析,不动 CLI 契约): - 新增 resolvePromptEnhanceModelFacts / resolvePromptEnhanceTarget:从 Selection View 的完整 Model Config 取输出上限与档位集合,预算直接取模型声明的上限 (与 workspace/generateText 非 git 分支同口径);档位落到模型集合上,default 与 不支持的档位都回落到模型默认档(values 末位),并回传被替换的档位供留轨迹。 - 模型不在已发布列表、或无选型时不再发请求(构造不出合法请求);模型视图未就绪时 入口直接禁用,避免把加载中的瞬态说成配置问题。 - 解析模块改用最小结构性 View 形状,测试替身不再是 as unknown as 断言。 - 文档与 shared 注释同步:这两条契约、以及推理档位是 Registry 拒绝而非 provider 静默归一化。 未验证:真实模型链路上的效果需要 provider 凭据;改动需重启 `pnpm dev:desktop` 生效。
洁癖收尾(知识同步):把 docs/prompt-enhance.md 里与最终实现不一致的现役说法改回 真实行为,并清掉实现过程叙事。 - 「增强」禁用条件补上「模型视图未就绪」(modelSelectionView === null)。 - 日志语义补全:可恢复异常各留一条 warn(档位被回退、取消未送达 / Host 未找到待取消 请求、无可用选型、回填未完整落地、模型返回空内容、scope 已变化)。 - 手动验证清单补两条模型契约场景(独立通道档位设「默认」仍能发起;模型被删后给出 可读提示而不是模型校验错误)。 - 设置分区的控件清单按实际用的组件写(去掉未使用的 Input,补 SettingsGroupCard 与 Button)。 - 文案命名规则改成只讲当前事实,不再记叙旧键的删除过程。 - 文档开头不再写成「待实施」的口径。 - oxfmt:docs/prompt-enhance.md 与 packages/ui/test/promptEnhance.test.ts(本次新增 文件,仓库仍有 97 个历史格式漂移文件未动)。 验证:promptEnhance 测试 21 项通过;typecheck 通过;oxlint 0 error(63 条既有 warning);architecture:check --changed 0 新增;文档里 6 段模板正文仍与 prompts.ts 逐字一致(脚本比对)。
症状:点击「增强提示词」报 "Model request failed.",网关使用记录显示
调用成功但输入输出 token 均为 0。
根因:workspace/generateText 走 AI SDK 非流式 doGenerate,CPA 这类
openai-compatible 网关的非流式响应包在 {"success":…,"data":…} 自定义
信封里,AI SDK 按标准 OpenAI 形状做 schema 校验失败后统一报 Invalid
JSON response;同一网关的流式 SSE 是标准格式(当天主回合流式 1224 次
全部成功,非流式 3/3 全败,curl 重放已复现信封)。网关记账 0 token 是
其自身口径,上游实际已生成增强结果。
修复:generateWorkspaceTextImpl 改用 model.streamText 并以
accumulateWorkspaceGenerateTextStream 累积出与非流式等价的结果
(text/finishReason/usage/toolCalls),与主回合执行链、连通性探测同
一条传输路径;Git 提交消息生成同一入口一并受益。取消不受影响(仍是
operationId → AbortController)。回归测试 5 例 colocated 于
workspace-generate-text-accumulate.test.ts 并登记进 CI Focused tests。
症状:模型调用已成功(网关记录正常、model-io 已捕获增强结果文本), 但 UI 报「写入输入框失败,草稿保持不变」,草稿最终停留原文。 根因:replaceEditorText 的 editor.update 未带 discrete,Lexical 非 discrete 更新走批量异步提交;回填三连写完后立即用 getMarkdown() 读回 的是尚未提交的旧 state,读回比对必然失败,走「写回原文」分支。用 headless Lexical 0.42 探针验证:非 discrete 写入后立即读为空旧值, await 一个微任务后才可见;discrete 写入后立即读即新值。 修复:replaceEditorText 的 update 加 discrete: true(与 prependEditorMentionIfMissing 的 discrete 先例同口径),setText 契约 变为「调用返回即已落地」。全部调用方(草稿预填、发送失败回滚、增强 回填/还原、clear)都是整替内容的程序化写入,同步提交只会更正确。 读回比对的恒等性依赖 $getPromptMarkdown 纯序列化(无转义),纯文本 往返恒等;该约束已写入 docs/prompt-enhance.md 回填段。
依据 issue #3(附件被伪装成历史 Read 工具结果、且与用户消息脱钩,模型 因此把附件当背景资料而答非所问)先落规范再改实现。 规范要点:措辞只在 buildPromptAttachmentReminderBodies 一处生成,两条 投递路径与 hydrate 路径共用;删除伪造的 Called/Result of calling the Read tool 外壳,改为明话附件框法(名称 + 路径 + 数据边界句 + 内容完整性 说明);删除要求模型向用户隐瞒截断的语句;保留行号正文。截断对用户可见 列为阶段二,需先定稿 resolve 之后的投影承载通道。
症状(issue #3):上传文本附件后正文只写「读取文档内容」,模型不总结 附件,反而去遍历附件所在目录、读取其它文件后答非所问。 根因:prompt-attachment.ts 的 kind=file 分支把附件渲染成 `Called the Read tool with the following input: {file_path}` + `Result of calling the Read tool:` 两个 system-reminder 块,且该提醒 经 prompt_attachment 元上下文通道以独立消息投递(isMeta)。用户消息 本身不含任何附件痕迹,因此模型既无法区分「刚附上」与「早前读过」, 也拿不到用户指令的指代对象。 修复(阶段一,纯措辞): - 删除伪造的 Read 工具外壳,改为明话附件框法:name + path + 行号正文; - 保留「数据、非指令」边界句,内容完整时显式说明不必重复 Read; - 截断时如实写明「前 N 行 / 共 M 行」,删除要求模型向用户隐瞒截断的语句; - 措辞只在 buildPromptAttachmentReminderBodies 一处生成,live 与 hydrate 共用(新增同形断言防漂移),两条投递路径同时生效。 阶段二(截断对用户可见)单独成批:live 侧的附件展示元信息必须由一条 post-resolve 的 additive 事件送达(TurnStarted 早于附件 resolve,投影 层无 parts 重建路径),跨 contracts/归一化/投影/UI 四层,需要运行桌面端 验证,已写入 docs/prompt-attachment.md。 验证:prompt-attachment 措辞单测 6/6、live/hydrate 同形 2/2,共 34 项 通过;pnpm typecheck(根 + @kcode/core)通过;pnpm lint 0 错误(63 条 基线告警不变);architecture:check --changed 0 违规。
阶段二(docs/prompt-attachment.md):让用户也能看到附件被截断,而不只是 模型知道。 事实来源保持唯一:截断只有 resolve 时才知道(read.truncated / totalLines 写进 FilePart.metadata.preview),展示层只消费、不自行推算——截断除了体积 超限还有 token 上限兜底,依赖内容,客户端算不出与 CLI 一致的结论。 - 新增 additive 会话事件 turn_attachments_resolved(仅展示用途,不进模型 上下文、不参与压缩与冷恢复合成,已归入 cold-event-merge 的 memory-only 分类,避免每次冷恢复刷 unclassified 诊断)。TurnStarted 早于附件 resolve, 无法携带该事实,这是 live 侧唯一的送达点。 - 载荷复用 TurnAttachmentMeta 并加可选 truncated / totalLines;缺省表示 未知,不得写成 false。 - 投影按行内序号与既有附件对齐,只补截断字段,不覆盖 ref / fileName / mime / bytes;未变化时不产生 delta。 - 冷恢复由 attachmentMetasOfMessage 从 part.metadata.preview 派生同一份 事实,与 live 一致。 - 展示:发送后的附件 chip 加「已截断」标记与悬浮说明(zh/en 同步); 发送前不展示(事实发送时才产生)。 验证:投影回归测试 4/4(补字段、不改既有字段、未截断不写入、无附件不产 生字段),CI Focused tests 全量 65/65;pnpm typecheck(根 + @kcode/core + @kcode/bootstrap)通过;pnpm lint 0 错误(63 条基线不变); architecture:check --changed 0 违规。
症状:发一个远超体积上限、但每行都很短的文件(如 20 万行短行), 模型只拿到前 2000 行,提示词却告诉它「It is complete as given」, 消息上也没有「已截断」标记——截断对模型和用户双双隐形。 根因:读取层只把 token 上限硬截标成 truncated;超限文件走 `limit: READ_DEFAULT_MAX_LINES` 的按行限流,属于 range view,读取层 一律返回 truncated=false(那是给 Read 的 readFileState 完整性守卫用 的语义)。附件预读直接复用了这个字段,于是「只交付前 2000 行」被判成 「完整」。 修复:新增 isPartialAttachmentTextRead(read)(truncated === true || numLines < totalLines),resolve 时用它一次性得出截断事实, metadata.preview.truncated 与 recoverability 与它同源,展示事件元信息 随之带上 truncated/totalLines。展示层仍只消费事实。 实测(真实文件系统端口): - 1138KB/12005 行中文文档:交付 984 行,truncated=true、totalLines=12005; - 修复前 20000 行短行文件:交付 2000 行、truncated=false、提示词称内容 完整、事件无标记;修复后 truncated=true、totalLines=20000、提示词改为 「Only the first 2000 lines are included」。 - 整文件读完与空文件(1/1)仍不判截断。 验证:新增 attachments 单测 6/6,附件相关 focused 测试 23/23;pnpm typecheck(根 + @kcode/core)通过;pnpm lint 0 错误(63 条基线告警不 变);architecture:check --changed 0 违规;agent bundle 已重建并确认含 新判定。
问题:默认闸门把附件、网页元素/PPT/代码评论/对话选区引用与 mention 一起拦下, 但取证发现前四类根本不在编辑器里——附件在 composerAttachmentUploadStore、四类引用 是各自 hook 的组件 state,草稿记录 V4ComposerDraft 里没有它们的字段,回填三连 碰不到;只有行内引用是编辑器节点。于是「加了附件就不能增强」属于纯误拦; 而 mention 判定用 parseMentionMarkdown 解析文本形态,还会把「解释一下 $PATH」 「看看 /tmp 目录」这类纯文本草稿误判成引用。 改法:判据换成「回填会不会毁掉它」。 - gates.ts:入参改为 hasInlineReferences + allowInlineReferenceRewrite,删掉 附件/引用/文本形态解析;拒绝原因 structuredDraft → inlineReference。 - LexicalChatInput 句柄新增 hasInlineReferences(),遍历编辑器节点判 $isPromptMentionNode; composer 按 readDraftText 同族注入读取器(readHasInlineReferences)。 - 设置字段改名 allowStructuredOverwrite → allowInlineReferenceRewrite;标签改为 「允许改写草稿里的行内引用」,说明小字按定稿文案「行内引用会变成纯文本」; 被拒 toast 键改名 inlineReferenceBlocked,文案只说行内引用(中英同步)。 - 单测矩阵同步:有节点才拒、放开后放行、附件/手打 token/普通链接一律放行。 - spec(docs/prompt-enhance.md)同步判决依据表、判定入口与已知边界。 门禁:typecheck、lint(0 错误)、architecture:check --changed(0 违规)、 CI focused tests 53/53。旧字段残留在 setting.json 不会导致设置加载失败 (appSettings 非 strict,未知键被剥离,新字段取默认)。
guide 被 drain 时直接内联进当前轮,没有「自己那一轮」,主路径的 turn_attachments_resolved 永远不会为它发射;且当前轮已有原输入行, 按 turnId 补发会错把截断标记打到原输入行上。busy 中引导发送超限 附件时,live 的「已截断」标记因此永不出现(冷恢复由 parts 派生, 反而有),两条路径表现分叉。 修复方式:TurnSteerDrained 载荷的 drainedInputs[] 新增可选 attachments(TurnAttachmentMeta 数组,additive,缺省表示未知)。 - core:drain 时 guide 输入把 resolve 后的 summarizeResolvedTurnAttachmentsForEvent() 结果写入事件载荷; queue 不携带(提升后走主路径 resolve 补发,语义不变)。 - 投影:新增 steerDrainedRowAttachments(),以 intent.attachmentRefs 为基准(保留稳定 ref)按行内序号合并截断字段;无 refs 时直接 采用自带元信息。 - 冷恢复:合成 guide 的 TurnSteerDrained 时用 attachmentMetasOfMessage() 从 parts 派生同形状载荷,live/冷恢复 同口径。 - 测试:turn-attachments-resolved-projection.test.ts 新增 4 个 guide 场景(自带截断且保留 ref、无 refs 直采用、未截断零字段且 原输入行不受影响、无附件保持旧行为)。 - spec:docs/prompt-attachment.md 同步新增条款与验收场景,修正 原先「排队/引导输入都由自己那一轮补发」的错误表述。 顺手清理:ConversationComposer 的 leadingActionsNode memo 依赖里 删除闸门收窄后不再使用的 5 个依赖(hasAttachments 等),消除 多余的整簇工具条重渲染。 验证:tsx --test 52/52 全绿;pnpm typecheck / lint(0 error)/ architecture:check --changed(0 违规)通过。chip 的 live 表现 仍需 pnpm dev:desktop 手动确认(spec 手动验证范围)。
清理 spec 审查发现的两个轻微残留: - settings.ts 原以值形式导入 PROMPT_ENHANCE_SETTINGS_DEFAULTS, 不满足 spec「promptEnhance 纯模块对 @kcode/shared 只用 type-only 导入」的字面约束。改为内联本地默认值常量(与 shared 常量逐字一致),并由 promptEnhance.test.ts 新增漂移断言锁住 两份不漂移:任何一侧改默认值而另一侧没跟上,测试当场红。 - usePromptEnhance 的两处 scope 变化日志(作废在途增强、丢弃 迟到结果)从 info 升为 warn,对齐 spec「可恢复异常各留一条 warn」的清单——在途请求作废属生命周期边界事件,不是正常流程。 - spec(docs/prompt-enhance.md)模块清单同步注明默认值内联与 漂移锁。 验证:tsx --test promptEnhance 22/22(含新漂移锁);typecheck / lint(0 error)/ architecture:check --changed(0 违规)通过。
新登记的 3 个 core 测试文件(attachments、prompt-attachment-parity、 workspace-generate-text-accumulate)经 hydrator 间接 import create-workflow-graph-bounds.ts,后者从 @kcode/dynamic-workflow/projections 取值,而该子路径在 package.json 的 exports 里直接指向 dist/projections.js。 CI 是全新检出,根目录 typecheck 只做 --noEmit、不产出 dist,Focused tests 步骤原先只构建了 @kcode/contracts,于是这 3 个文件整个以 ERR_MODULE_NOT_FOUND 失败(本地因 dist 齐全而看不到,上游 main 的 CI 因为 清单里没有 core 测试也一直是绿的)。在同一个 step 补一条 pnpm --filter @kcode/dynamic-workflow build。 验证:模拟全新检出(移走除 contracts 外全部 20 个 dist)后按新顺序构建, Focused tests 76/76、release-signing-plan 4/4,无模块缺失;typecheck 退出 0、lint 0 error(63 条既有 warning)、architecture:check --changed 0 违规。 两份 spec 中「新测试文件必须登记进 ci.yml」的条款同步补上构建产物前提。
回应 PR 7836246#5 上 Copilot 的 4 条 review 意见: - HIGH(usePromptEnhance:373):编辑器在增强进行中不受 running 约束 (runningStartedAt 只作用于工具条按钮),原先只挡 scope 变化,用户在 等待期间补写的内容会被迟到的结果整条覆盖,而随后立下的还原点只含发起 时的原文,那些新输入再无找回路径。新增回填闸 evaluatePromptEnhanceFill:以发起时的草稿快照为基准比对(归一化口径 与其余比对一致),不一致即丢弃结果、不立还原点、不覆盖并提示。 - MEDIUM(usePromptEnhance:251):补一条只含 cleanup 的 effect,组件 卸载时作废 run 并按发起时固化的 operationId 发出与取消同一条 best-effort 通知,避免迟到结果回填已离开会话的草稿、Host 请求空跑到 超时。 - MEDIUM(usePromptEnhance:435):还原点改到「读回确认写入已落地」之后 才清,写异常与读回不一致都保留还原点并提示 restoreFailed,不再出现 「原文没写回来、还原点也没了、却报成功」。还原与回填因此共用 writeDraftVerified 这一条写入路径,restore 里内联的那份重复 try/catch 一并收敛。 - LOW(prompts.ts:54):basic 模板与 spec 同处把 Constrains 改为 Constraints(文档模板与代码要求逐字一致)。 i18n 新增 draftChanged / restoreFailed 两条,zh-CN 与 en-US 同键。 验证:tsx --test promptEnhance 23/23(含新增回填闸回归测试); pnpm typecheck 退出 0;pnpm lint 0 error(63 条既有 warning,与基线 一致);architecture:check --changed 0 违规;模拟全新检出(移走除 contracts 外全部 21 个 dist,按 ci.yml 顺序构建)Focused tests 77/77、 release-signing-plan 4/4。 docs/prompt-enhance.md 同步:用户故事 7 扩到「在途改动一律不被覆盖」、 流程图补回填闸与卸载取消、新增回填闸/卸载/还原清点顺序三段说明、日志 与测试决策清单更新、手动验证补两条场景(这两条仍需 pnpm dev:desktop 在真实模型调用下过一遍)。
887fe9d(让 TurnSteerDrained 自带截断事实)留下两处类型错误: - product-projection.ts 的 steerDrainedRowAttachments 声明返回 { attachments: ... } 必填,但「既无 intent.attachmentRefs 也无自带元信息」 那一支 return {},类型与实现自相矛盾(TS2741)。改为 attachments 可选: 两个非空分支都必有该字段,只有空对象分支不带,而调用方是 spread,字段 缺席即「无附件」。 - 同提交新增的测试 helper 手写了一份窄化的附件类型,漏掉 truncated / totalLines,于是两条「guide drain 自带截断事实」用例本身编译不过 (TS2353 ×2)。改为直接用契约里的 TurnAttachmentMeta:以后契约加字段会在 编译期暴露,而不是把用例悄悄变成不可编译。 影响不止测试:pnpm --filter @kcode/bootstrap build(tsc)失败会让 scripts/build-desktop-agent-cli.mjs 失败,pnpm dev:desktop 在 Electron 起来 之前就退出。CI 抓不到这类错误——根目录 typecheck 不覆盖 apps/kcode-cli/packages/*,lint 是 oxlint(不做类型检查),focused tests 走 tsx(类型被剥掉),所以带这个错误的提交可以「CI 全绿地合入」。 验证:bootstrap tsc --noEmit 退出 0;turn-attachments-resolved-projection 8/8;node scripts/build-desktop-agent-cli.mjs 退出 0;pnpm dev:desktop 正常 起 Electron 并渲染 chat 区。
只装了 Command Line Tools 的 macOS 机器上,toolchain 自带的 Swift 兼容库 (libswiftCompatibility*.a)只有 arm64 切片,-target x86_64-apple-macos11 的链接必然失败(ld: fat file missing arch 'x86_64';换 macos12 目标同样 失败,本机要 macos13 才链得上)。原脚本一条 slice 失败就整体放弃,结果是 「什么都没产出」:resources/macos-window-bounds/ 里只剩一个 -arm64 残片, 正式的 kcode-window-bounds 不存在,于是 ensure-local-runtime-assets 每次 dev 都重跑一遍这个必然失败的构建,权限浮窗也因为拿不到 bounds 数据源而 失去吸附。 改为逐片构建、成功几片算几片: - 两片都成功 → lipo 出 universal(原行为不变); - 只剩一片 → 直接复用它作为产物,并明确警告「发布包若需覆盖另一架构,请在 完整 Xcode(含双架构 Swift 兼容库)下重新构建」; - 全失败 → 保留原来的 warn 后 exit 0(吸附属观感增强,不该让构建挂掉)。 中间 slice 一律在 finally 里清掉,不再把残片留在 resources 里。 验证:本机(CLT-only,x86_64 slice 必然失败)跑 packages/desktop/scripts/build-macos-window-bounds.mjs,产出 arm64 单架构 kcode-window-bounds、无中间文件残留、退出码 0;pnpm dev:desktop 的 pre-dev 报 all local runtime assets are ready(此前每次启动都要重跑失败构建)。 未验证:双架构 lipo 成功分支(本机 toolchain 造不出 x86_64 slice)。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概述
本 PR 落地两项各自带自包含 spec 的功能,以及审查后补充的两处修复:
docs/prompt-enhance.md):composer(v4 输入区)工具条新增「增强 / 还原 / 设置」入口,按三档模式(基础 / 编程任务 / 创意)改写草稿并原地回填,绝不自动发送;支持取消、还原点与完整设置分区。docs/prompt-attachment.md):修 issue 能建个群吗? #3 —— 附件不再被伪装成历史 Read 工具结果,改为明话附件框法;截断状态如实说明,并在消息附件 chip 上标出「已截断」。提示词增强
packages/ui/src/v4/composer/promptEnhance/8 个纯模块(模板 / 拼装 / 闸门 / run 跟踪 / 取消句柄 / 请求参数 / 设置补齐 / 通道解析),全部不依赖 React,对 shared 仅 type-only 依赖,可直接tsx --test。generateWorkspaceText链路,querySource=prompt_enhance;取消走operationId(AbortSignal 过不了 RPC JSON 序列化);请求自带输出预算(取模型声明上限)与档位回落契约。Invalid JSON response失败;Git 提交消息同入口一并受益。$PATH//tmp等不再被误拦;allowInlineReferenceRewrite可显式放开放行。PromptEnhanceSection注册进basics分组,i18n 中英同步,旧chat.promptEnhance.*命名空间删除。附件表达与截断可见
truncated:false的 range view;展示元信息与recoverability同源,不再一处判截断、另一处报provider_ready。turn_attachments_resolved(additive、仅展示)把截断事实下发到 live 投影;冷恢复从part.metadata.preview派生同一形状;chip 标记与 tooltip 中英同步。TurnSteerDrained.drainedInputs[].attachments自带——guide 没有自己那一轮,主路径事件不会为它发射,按 turnId 补发还会错打到同轮的原输入行。审查后修复(本 PR 末尾两个提交)
887fe9d fix: 引导输入附件的截断标记改由 TurnSteerDrained 自带dafe9e9 chore: 增强模块改 type-only 导入并规范 scope 变化日志验证
pnpm typecheck通过;pnpm lint0 error(63 个 warning 均为存量文件既有告警);pnpm architecture:check --changed0 违规。.github/workflows/ci.yml的 Focused tests,本地tsx --test合计 52/52 通过。docs/prompt-enhance.md逐字比对一致(脚本与测试双确认)。待人工确认
pnpm dev:desktop)尚未执行:三档各跑一次增强、进行中取消、还原与拒还原、设置持久化、自动通道跟随模型切换;附件 chip 的 live 截断标记(含 busy 中引导发送)及刷新后一致性。说明
157079d(新增.kcodeignore与增强实现规范),随分支基线一并进入本 PR。