flavor-code 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
 
14
14
  `flavor-code` 是一个同时提供终端界面与 Electron 桌面应用的 AI 编程助手。它接入大语言模型(OpenAI GPT、Anthropic Claude 或任何兼容服务),能理解你的项目结构,在工作区范围内安全操作文件,甚至能把复杂任务拆成多块,分给多个"小助手"并行处理。
15
15
 
16
- 当前稳定版本:**1.2.1**
16
+ 当前稳定版本:**1.2.3**
17
17
 
18
18
  ## 它能做什么
19
19
 
@@ -45,9 +45,18 @@
45
45
 
46
46
  同一次 `Task` 调度现在只冻结一次主 Agent 的模型可见上下文。每个子 Agent 都从这份快照创建独立副本,完整复用 system prompt、`FLAVOR.md`、任务状态、压缩摘要和父会话历史,只在最后追加自己的角色约束与任务 directive。共享部分保持消息顺序和 UTF-8 字节一致,可提高 Anthropic Prompt Cache 与 OpenAI Automatic Prompt Caching 的命中机会,同时父子消息、压缩和 usage 状态仍然彼此隔离。
47
47
 
48
- Anthropic 请求会在 fork 边界发送显式 `cache_control`;OpenAI 与 OpenAI-compatible 服务继续使用自动缓存,不注入可能与旧模型不兼容的专用字段。缓存仍受提供商规则限制:短于最小 token 门槛的前缀不会缓存;主/子 Agent 工具定义或模型不同会阻止整包父子命中;首批完全并发的 Anthropic 子请求也可能在缓存写入可见前同时发生 miss。后续兄弟任务、依赖节点和重试仍可复用相同的父前缀。
49
-
50
- ### 提示词缓存优化与命中率量化(1.2.0 / 1.2.1)
48
+ Anthropic 请求会在 fork 边界发送显式 `cache_control`;OpenAI 与 OpenAI-compatible 服务继续使用自动缓存,不注入可能与旧模型不兼容的专用字段。缓存仍受提供商规则限制:短于最小 token 门槛的前缀不会缓存;主/子 Agent 工具定义或模型不同会阻止整包父子命中;首批完全并发的 Anthropic 子请求也可能在缓存写入可见前同时发生 miss。后续兄弟任务、依赖节点和重试仍可复用相同的父前缀。
49
+
50
+ ### OpenAI-compatible 工具调用兼容修复(1.2.3)
51
+
52
+ OpenAI Responses 流式适配器现在同时兼容官方事件序列和部分兼容端点的精简事件序列:
53
+
54
+ - 官方端点通过 `response.function_call_arguments.done` 完成工具参数时,保持原有解析行为。
55
+ - 兼容端点省略参数完成事件、只在 `response.output_item.done` 中返回完整 `function_call` 时,也能正确提取工具名、调用 ID 和参数,不再把本轮误判为“无工具调用”并提前结束。
56
+ - 同一工具调用同时出现两种完成事件时,按 `output_index` 去重,避免工具被重复执行。
57
+ - 修复仅位于 OpenAI Responses 适配层;Anthropic Messages 请求、`tool_use` / `tool_result` 映射和缓存断点逻辑保持不变。
58
+
59
+ ### 提示词缓存优化与命中率量化(1.2.0 / 1.2.1)
51
60
 
52
61
  1.1.9 把字节级缓存思想扩展到**主会话本身**;1.2.0 重新划分了缓存布局,并加入了按 provider 的缓存能力识别;1.2.1 用滚动尾部断点把**整段对话历史**纳入缓存:
53
62
 
@@ -530,7 +539,7 @@ npm run desktop:dist # 生成 Windows NSIS 安装包
530
539
  Windows 打包产物位于:
531
540
 
532
541
  - 免安装目录:`release/win-unpacked/Flavor Code.exe`
533
- - NSIS 安装包:`release/Flavor-Code-1.2.1-x64.exe`
542
+ - NSIS 安装包:`release/Flavor-Code-1.2.3-x64.exe`
534
543
 
535
544
  模型配置仍读取全局 `~/.flavor-code/flavor.json`、项目 `.flavor/flavor.json`、`.env` 和环境变量,因此 CLI 与桌面端可以共享配置与会话。生产版桌面窗口启用了 `contextIsolation` 和 Chromium 沙箱,关闭了渲染进程的 Node.js 集成;文件、命令和 Agent 操作只通过显式 IPC 接口进入主进程。Windows 的 `desktop:dev` 为兼容工作区内 Chromium 子进程启动,仅在本地开发启动器中使用 `--no-sandbox`,打包产物不携带该参数。
536
545
 
@@ -14,7 +14,7 @@ import {
14
14
  modelContentTranscriptText,
15
15
  redactErrorText,
16
16
  transcriptReducer
17
- } from "./chunk-BU64GNXE.js";
17
+ } from "./chunk-XGCFBGBB.js";
18
18
  import "./chunk-MVIMQEQT.js";
19
19
  import {
20
20
  Box_default,
@@ -3182,4 +3182,4 @@ export {
3182
3182
  submitSafely,
3183
3183
  taskPanelViewportRows
3184
3184
  };
3185
- //# sourceMappingURL=app-WC2XXGLM.js.map
3185
+ //# sourceMappingURL=app-SCHNJSXI.js.map
@@ -4,7 +4,7 @@ import {
4
4
  message,
5
5
  redactErrorText,
6
6
  redactSecrets
7
- } from "./chunk-BU64GNXE.js";
7
+ } from "./chunk-XGCFBGBB.js";
8
8
 
9
9
  // src/rpc/server.ts
10
10
  import { createInterface } from "readline";
@@ -243,4 +243,4 @@ export {
243
243
  TraceRecordSchema,
244
244
  TraceRecorder
245
245
  };
246
- //# sourceMappingURL=chunk-M744K7MK.js.map
246
+ //# sourceMappingURL=chunk-AHUOGT4I.js.map
@@ -7757,6 +7757,7 @@ var OpenAIModelAdapter = class {
7757
7757
  async *stream(request) {
7758
7758
  const callIds = /* @__PURE__ */ new Map();
7759
7759
  const pendingCalls = /* @__PURE__ */ new Map();
7760
+ const emittedCalls = /* @__PURE__ */ new Set();
7760
7761
  try {
7761
7762
  const body = {
7762
7763
  model: request.model,
@@ -7771,20 +7772,34 @@ var OpenAIModelAdapter = class {
7771
7772
  };
7772
7773
  const stream = this.client.responses.stream(body, { signal: request.signal });
7773
7774
  for await (const event of stream) {
7774
- if ((event.type === "response.output_item.added" || event.type === "response.output_item.done") && event.item?.type === "function_call" && event.output_index !== void 0 && event.item.call_id) {
7775
+ if (event.type === "response.output_item.added" && event.item?.type === "function_call" && event.output_index !== void 0 && event.item.call_id) {
7775
7776
  callIds.set(event.output_index, event.item.call_id);
7776
7777
  const pending = pendingCalls.get(event.output_index);
7777
- if (pending) {
7778
+ if (pending && !emittedCalls.has(event.output_index)) {
7778
7779
  yield toolCallEvent(event.item.call_id, pending.name, pending.arguments);
7780
+ emittedCalls.add(event.output_index);
7781
+ pendingCalls.delete(event.output_index);
7782
+ }
7783
+ } else if (event.type === "response.output_item.done" && event.item?.type === "function_call" && event.output_index !== void 0 && event.item.call_id) {
7784
+ callIds.set(event.output_index, event.item.call_id);
7785
+ if (!emittedCalls.has(event.output_index)) {
7786
+ const pending = pendingCalls.get(event.output_index);
7787
+ yield toolCallEvent(
7788
+ event.item.call_id,
7789
+ pending?.name ?? event.item.name,
7790
+ pending?.arguments ?? event.item.arguments
7791
+ );
7792
+ emittedCalls.add(event.output_index);
7779
7793
  pendingCalls.delete(event.output_index);
7780
7794
  }
7781
7795
  } else if (event.type === "response.output_text.delta" && event.delta) {
7782
7796
  yield { type: "text", text: event.delta };
7783
7797
  } else if (event.type === "response.function_call_arguments.done" && event.output_index !== void 0 && event.name) {
7784
7798
  const callId = callIds.get(event.output_index);
7785
- if (callId) {
7799
+ if (callId && !emittedCalls.has(event.output_index)) {
7786
7800
  yield toolCallEvent(callId, event.name, event.arguments ?? "");
7787
- } else {
7801
+ emittedCalls.add(event.output_index);
7802
+ } else if (!emittedCalls.has(event.output_index)) {
7788
7803
  pendingCalls.set(event.output_index, {
7789
7804
  name: event.name,
7790
7805
  arguments: event.arguments ?? ""
@@ -15768,4 +15783,4 @@ export {
15768
15783
  createExecutionEnvironment,
15769
15784
  createProductionRuntime
15770
15785
  };
15771
- //# sourceMappingURL=chunk-BU64GNXE.js.map
15786
+ //# sourceMappingURL=chunk-XGCFBGBB.js.map