@tencent-ai/agent-sdk 0.3.157 → 0.3.158
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/cli/CHANGELOG.md +24 -0
- package/cli/dist/codebuddy-headless.js +214 -209
- package/cli/dist/web-ui/assets/index-C5x-jWxM.css +32 -0
- package/cli/dist/web-ui/assets/{index-bVNRRvKC.js → index-CU_ExRgj.js} +179 -167
- package/cli/dist/web-ui/assets/workbox-window.prod.es5-BBnX5xw4.js +2 -0
- package/cli/dist/web-ui/docs/cn/cli/goal.md +161 -0
- package/cli/dist/web-ui/docs/cn/cli/hooks.md +12 -4
- package/cli/dist/web-ui/docs/cn/cli/release-notes/README.md +2 -0
- package/cli/dist/web-ui/docs/cn/cli/release-notes/v2.98.0.md +48 -0
- package/cli/dist/web-ui/docs/cn/cli/release-notes/v2.98.1.md +19 -0
- package/cli/dist/web-ui/docs/cn/cli/slash-commands.md +1 -0
- package/cli/dist/web-ui/docs/en/cli/goal.md +161 -0
- package/cli/dist/web-ui/docs/en/cli/hooks.md +10 -2
- package/cli/dist/web-ui/docs/en/cli/release-notes/README.md +2 -0
- package/cli/dist/web-ui/docs/en/cli/release-notes/v2.98.0.md +48 -0
- package/cli/dist/web-ui/docs/en/cli/release-notes/v2.98.1.md +19 -0
- package/cli/dist/web-ui/docs/en/cli/slash-commands.md +1 -0
- package/cli/dist/web-ui/docs/search-index-en.json +1 -1
- package/cli/dist/web-ui/docs/search-index-zh.json +1 -1
- package/cli/dist/web-ui/docs/sidebar-en.json +1 -1
- package/cli/dist/web-ui/docs/sidebar-zh.json +1 -1
- package/cli/dist/web-ui/index.html +2 -2
- package/cli/dist/web-ui/sw.js +1 -1
- package/cli/dist/web-ui/{workbox-e082a648.js → workbox-fed2bdfe.js} +1 -1
- package/cli/package.json +1 -1
- package/cli/product.cloudhosted.json +4 -3
- package/cli/product.internal.json +4 -3
- package/cli/product.ioa.json +25 -3
- package/cli/product.json +27 -5
- package/cli/product.selfhosted.json +4 -3
- package/lib/auth.js +3 -2
- package/lib/auth.js.map +1 -1
- package/lib/connect.js +3 -2
- package/lib/connect.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/mcp/create-sdk-mcp-server.js +3 -2
- package/lib/mcp/create-sdk-mcp-server.js.map +1 -1
- package/lib/plugin.js +13 -22
- package/lib/plugin.js.map +1 -1
- package/lib/query.d.ts.map +1 -1
- package/lib/query.js +2 -2
- package/lib/query.js.map +1 -1
- package/lib/session.js +4 -4
- package/lib/session.js.map +1 -1
- package/lib/transport/index.js +2 -2
- package/lib/transport/index.js.map +1 -1
- package/lib/transport/process-transport.js +7 -17
- package/lib/transport/process-transport.js.map +1 -1
- package/lib/utils/cli-resolver.js +6 -6
- package/lib/utils/cli-resolver.js.map +1 -1
- package/lib/utils/env-utils.js +2 -1
- package/lib/utils/env-utils.js.map +1 -1
- package/lib/utils/process.js +2 -1
- package/lib/utils/process.js.map +1 -1
- package/lib/utils/type-guards.js +2 -1
- package/lib/utils/type-guards.js.map +1 -1
- package/package.json +1 -1
- package/cli/dist/web-ui/assets/index-CY6b2fbj.css +0 -32
- package/cli/dist/web-ui/assets/workbox-window.prod.es5-BIl4cyR9.js +0 -2
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
try{self["workbox:window:7.4.0"]&&_()}catch{}function b(t,r){return new Promise((function(n){var u=new MessageChannel;u.port1.onmessage=function(s){n(s.data)},t.postMessage(r,[u.port2])}))}function P(t,r){(r==null||r>t.length)&&(r=t.length);for(var n=0,u=Array(r);n<r;n++)u[n]=t[n];return u}function j(t,r,n){return r&&(function(u,s){for(var c=0;c<s.length;c++){var o=s[c];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(u,W(o.key),o)}})(t.prototype,r),Object.defineProperty(t,"prototype",{writable:!1}),t}function S(t,r){var n=typeof Symbol<"u"&&t[Symbol.iterator]||t["@@iterator"];if(n)return(n=n.call(t)).next.bind(n);if(Array.isArray(t)||(n=(function(s,c){if(s){if(typeof s=="string")return P(s,c);var o={}.toString.call(s).slice(8,-1);return o==="Object"&&s.constructor&&(o=s.constructor.name),o==="Map"||o==="Set"?Array.from(s):o==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o)?P(s,c):void 0}})(t))||r){n&&(t=n);var u=0;return function(){return u>=t.length?{done:!0}:{done:!1,value:t[u++]}}}throw new TypeError(`Invalid attempt to iterate non-iterable instance.
|
|
2
|
+
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function w(t,r){return w=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(n,u){return n.__proto__=u,n},w(t,r)}function W(t){var r=(function(n,u){if(typeof n!="object"||!n)return n;var s=n[Symbol.toPrimitive];if(s!==void 0){var c=s.call(n,u);if(typeof c!="object")return c;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(n)})(t,"string");return typeof r=="symbol"?r:r+""}try{self["workbox:core:7.4.0"]&&_()}catch{}var m=function(){var t=this;this.promise=new Promise((function(r,n){t.resolve=r,t.reject=n}))};function y(t,r){var n=location.href;return new URL(t,n).href===new URL(r,n).href}var d=function(t,r){this.type=t,Object.assign(this,r)};function l(t,r,n){return t&&t.then||(t=Promise.resolve(t)),r?t.then(r):t}function k(){}var L={type:"SKIP_WAITING"};function E(t,r){return t&&t.then?t.then(k):Promise.resolve()}var O=(function(t){function r(c,o){var e,i;return o===void 0&&(o={}),(e=t.call(this)||this).nn={},e.tn=0,e.rn=new m,e.en=new m,e.on=new m,e.un=0,e.an=new Set,e.cn=function(){var f=e.fn,a=f.installing;e.tn>0||!y(a.scriptURL,e.sn.toString())||performance.now()>e.un+6e4?(e.vn=a,f.removeEventListener("updatefound",e.cn)):(e.hn=a,e.an.add(a),e.rn.resolve(a)),++e.tn,a.addEventListener("statechange",e.ln)},e.ln=function(f){var a=e.fn,v=f.target,h=v.state,p=v===e.vn,g={sw:v,isExternal:p,originalEvent:f};!p&&e.mn&&(g.isUpdate=!0),e.dispatchEvent(new d(h,g)),h==="installed"?e.wn=self.setTimeout((function(){h==="installed"&&a.waiting===v&&e.dispatchEvent(new d("waiting",g))}),200):h==="activating"&&(clearTimeout(e.wn),p||e.en.resolve(v))},e.yn=function(f){var a=e.hn,v=a!==navigator.serviceWorker.controller;e.dispatchEvent(new d("controlling",{isExternal:v,originalEvent:f,sw:a,isUpdate:e.mn})),v||e.on.resolve(a)},e.gn=(i=function(f){var a=f.data,v=f.ports,h=f.source;return l(e.getSW(),(function(){e.an.has(h)&&e.dispatchEvent(new d("message",{data:a,originalEvent:f,ports:v,sw:h}))}))},function(){for(var f=[],a=0;a<arguments.length;a++)f[a]=arguments[a];try{return Promise.resolve(i.apply(this,f))}catch(v){return Promise.reject(v)}}),e.sn=c,e.nn=o,navigator.serviceWorker.addEventListener("message",e.gn),e}var n,u;u=t,(n=r).prototype=Object.create(u.prototype),n.prototype.constructor=n,w(n,u);var s=r.prototype;return s.register=function(c){var o=(c===void 0?{}:c).immediate,e=o!==void 0&&o;try{var i=this;return l((function(f,a){var v=f();return v&&v.then?v.then(a):a(v)})((function(){if(!e&&document.readyState!=="complete")return E(new Promise((function(f){return window.addEventListener("load",f)})))}),(function(){return i.mn=!!navigator.serviceWorker.controller,i.dn=i.pn(),l(i.bn(),(function(f){i.fn=f,i.dn&&(i.hn=i.dn,i.en.resolve(i.dn),i.on.resolve(i.dn),i.dn.addEventListener("statechange",i.ln,{once:!0}));var a=i.fn.waiting;return a&&y(a.scriptURL,i.sn.toString())&&(i.hn=a,Promise.resolve().then((function(){i.dispatchEvent(new d("waiting",{sw:a,wasWaitingBeforeRegister:!0}))})).then((function(){}))),i.hn&&(i.rn.resolve(i.hn),i.an.add(i.hn)),i.fn.addEventListener("updatefound",i.cn),navigator.serviceWorker.addEventListener("controllerchange",i.yn),i.fn}))})))}catch(f){return Promise.reject(f)}},s.update=function(){try{return this.fn?l(E(this.fn.update())):l()}catch(c){return Promise.reject(c)}},s.getSW=function(){return this.hn!==void 0?Promise.resolve(this.hn):this.rn.promise},s.messageSW=function(c){try{return l(this.getSW(),(function(o){return b(o,c)}))}catch(o){return Promise.reject(o)}},s.messageSkipWaiting=function(){this.fn&&this.fn.waiting&&b(this.fn.waiting,L)},s.pn=function(){var c=navigator.serviceWorker.controller;return c&&y(c.scriptURL,this.sn.toString())?c:void 0},s.bn=function(){try{var c=this;return l((function(o,e){try{var i=o()}catch(f){return e(f)}return i&&i.then?i.then(void 0,e):i})((function(){return l(navigator.serviceWorker.register(c.sn,c.nn),(function(o){return c.un=performance.now(),o}))}),(function(o){throw o})))}catch(o){return Promise.reject(o)}},j(r,[{key:"active",get:function(){return this.en.promise}},{key:"controlling",get:function(){return this.on.promise}}])})((function(){function t(){this.Pn=new Map}var r=t.prototype;return r.addEventListener=function(n,u){this.jn(n).add(u)},r.removeEventListener=function(n,u){this.jn(n).delete(u)},r.dispatchEvent=function(n){n.target=this;for(var u,s=S(this.jn(n.type));!(u=s()).done;)(0,u.value)(n)},r.jn=function(n){return this.Pn.has(n)||this.Pn.set(n,new Set),this.Pn.get(n)},t})());export{O as Workbox,d as WorkboxEvent,b as messageSW};
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# 让 CodeBuddy 持续工作直到达成目标
|
|
2
|
+
|
|
3
|
+
> 用 `/goal` 设置一个完成条件,CodeBuddy 会跨多轮持续工作,直到条件满足才把控制权交还给你。
|
|
4
|
+
|
|
5
|
+
> **版本要求**:`/goal` 命令要求 `@tencent-ai/codebuddy-code` 已包含 goal 功能(agent-cli 的 `GoalService` 模块)。
|
|
6
|
+
|
|
7
|
+
`/goal` 命令设置一个完成条件,CodeBuddy 持续向其推进而无需你逐步催促。每轮(turn)结束时,由小模型(small-fast model)评估器判断条件是否成立——若不成立,CodeBuddy 自动开始下一轮,而不是把控制权交回给你。一旦条件满足,目标自动清除。
|
|
8
|
+
|
|
9
|
+
适合用 `/goal` 跟踪有可验证终态的实质性工作:
|
|
10
|
+
|
|
11
|
+
- 把一个模块迁到新 API,直到所有调用点都能编译且测试通过
|
|
12
|
+
- 实施一份设计文档,直到所有验收条件成立
|
|
13
|
+
- 把一个大文件拆成若干聚焦模块,直到每个模块都不超过尺寸预算
|
|
14
|
+
- 处理打了某个标签的 issue 列表,直到队列清空
|
|
15
|
+
|
|
16
|
+
本文涵盖:
|
|
17
|
+
|
|
18
|
+
- [与其他自治工作流对比](#与其他自治工作流对比):`/goal`、`/loop`、Stop hook 三者怎么选
|
|
19
|
+
- [设置目标](#设置目标)与[写好条件的要点](#写好一个有效的-condition)
|
|
20
|
+
- [查看状态](#查看状态)、[提前清除](#提前清除目标)、[非交互模式运行](#非交互模式运行)
|
|
21
|
+
- [评估机制](#评估机制如何工作)
|
|
22
|
+
- [实现说明与已知限制](#实现说明与已知限制)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## 使用 `/goal`
|
|
26
|
+
|
|
27
|
+
每个会话同时只能有一个 active goal。同一个命令根据参数差异承担"设置 / 查看 / 清除"三种角色。
|
|
28
|
+
|
|
29
|
+
### 设置目标
|
|
30
|
+
|
|
31
|
+
在 `/goal` 后跟你想满足的条件即可。如果当前已有 active goal,新的会替换旧的(旧 goal 的 hook 自动注销)。
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
/goal all tests in test/auth pass and the lint step is clean
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
设置完成后,CodeBuddy 会**立即开始一轮**,把"条件本身"作为指令交给主 agent——不需要你再额外发 prompt。同时输入框右下方会出现一行 `⊚ /goal active (Xs)` 指示器,每秒刷新已运行时长,让你随时知道当前处于 goal 模式。
|
|
38
|
+
|
|
39
|
+
每轮结束后,评估器会返回一段简短的 reason 解释"为什么条件还没/已满足"。这段 reason 会以 `isMeta=true` 的内部消息形式注入对话历史,让模型在下一轮看到 evaluator 的视角,从而精准补做欠缺的部分——这是模型能"知道还差哪几步"的关键。
|
|
40
|
+
|
|
41
|
+
> **会话级行为**:goal 持续运行直到条件满足或你执行 `/goal clear`。运行 `/goal`(无参数)查看 turns / tokens 等统计。
|
|
42
|
+
|
|
43
|
+
### 写好一个有效的 condition
|
|
44
|
+
|
|
45
|
+
[评估器](#评估机制如何工作)只会基于 CodeBuddy 在对话中**已经表达出来**的内容来判断条件,它不会自己跑命令、读文件。所以条件要写成"CodeBuddy 自己的输出能证明"的形式。"All tests in `test/auth` pass" 之所以可行,是因为 CodeBuddy 会自己跑测试,结果落在 transcript 里供评估器阅读。
|
|
46
|
+
|
|
47
|
+
一个能稳健支撑多轮工作的条件通常包含:
|
|
48
|
+
|
|
49
|
+
- **一个可度量的终态**:测试结果、构建退出码、文件数、空队列……
|
|
50
|
+
- **一种可证明方式**:例如 ``\`npm test\` exits 0`` 或 ``\`git status\` is clean``
|
|
51
|
+
- **不可破坏的约束**:路上不能改的东西,比如 "no other test file is modified"
|
|
52
|
+
|
|
53
|
+
condition 长度上限 **4000 字符**。
|
|
54
|
+
|
|
55
|
+
如果想给 goal 设置兜底上限,可以在 condition 里加上轮数 / 时间从句,例如 `or stop after 20 turns`,CodeBuddy 会在每轮里把当前进度对照该从句,evaluator 也能从对话中读出。
|
|
56
|
+
|
|
57
|
+
### 查看状态
|
|
58
|
+
|
|
59
|
+
不带参数运行 `/goal`:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
/goal
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
在 TUI 中会打开 goal recap 面板;在 Web UI / ACP 客户端中会通过 ACP 广播打开同等面板;在 headless / SDK 等没有 UI 的环境降级为纯文本输出。
|
|
66
|
+
|
|
67
|
+
面板内容包括:
|
|
68
|
+
- 条件
|
|
69
|
+
- 已运行时长
|
|
70
|
+
- 已评估的 turn 数
|
|
71
|
+
- token 消耗(goal 期间增量)
|
|
72
|
+
- 评估器最近一次给出的 reason
|
|
73
|
+
|
|
74
|
+
如果当前没有 active goal、但本会话内之前曾达成过一次 goal,面板会展示那次的 condition、duration、turn 数和 token 数。
|
|
75
|
+
|
|
76
|
+
### 提前清除目标
|
|
77
|
+
|
|
78
|
+
```text
|
|
79
|
+
/goal clear
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
下面这些 token 都视为 `clear` 的同义词:`stop`、`off`、`reset`、`none`、`cancel`。仅在**单 token 完全匹配**时识别为清除指令——`/goal stop using deprecated API` 仍按"设置新 condition"处理,不会被吞掉。
|
|
83
|
+
|
|
84
|
+
执行 `/clear` 重启会话也会一并移除 active goal(hook 注销 + meta 清理)。
|
|
85
|
+
|
|
86
|
+
### 在恢复会话时携带 goal
|
|
87
|
+
|
|
88
|
+
通过 `--resume` / `--continue` 恢复会话时,未完成的 goal 会被恢复(condition 与 scope 都还原)。
|
|
89
|
+
|
|
90
|
+
> **当前限制**:恢复时会沿用原 goal 的 createdAt / turnCount / token 起点,不重置计时器与计数器。如果你希望"重新计时",请先 `/goal clear` 再重新 `/goal <condition>`。已经达成或已被清除的 goal 不会被恢复(meta 已删)。
|
|
91
|
+
|
|
92
|
+
### 非交互模式运行
|
|
93
|
+
|
|
94
|
+
`/goal` 在[非交互模式(headless)](./headless.md)、[Remote Control](./remote-control.md) 中均可用。在 `-p` 模式下设置 goal 会让 evaluator 循环跑到完成:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
codebuddy -p "/goal CHANGELOG.md has an entry for every PR merged this week"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
需要在条件满足前提早终止,按 `Ctrl+C`。
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 评估机制如何工作
|
|
105
|
+
|
|
106
|
+
`/goal` 是对会话级 [prompt-based Stop hook](./hooks.md) 的一层封装。每当 CodeBuddy 主 agent 跑完一轮,**当前 condition + 当前对话** 会被一并发给配置好的小模型评估器。评估器返回一个"是 / 否 / 不可达"三态结果与简短 reason:
|
|
107
|
+
|
|
108
|
+
- **是(`ok: true`)**:清除 goal、记录"已达成"事件,UI 显示 `✔ Goal achieved` 状态条。
|
|
109
|
+
- **否(`ok: false`)**:把 reason 作为 `isMeta=true` 的 user message 注入 history(让主模型看到下一步该补什么),让 CodeBuddy 继续工作。同时写入一条 `goal-progress` UI 状态条 `◯ Goal not yet met… continuing`。
|
|
110
|
+
- **不可达(`ok: false, impossible: true`)**:用于评估器判断"在当前会话里这个目标根本不可能完成"(条件自相矛盾、依赖的能力/资源不可用、模型已经穷尽合理尝试)。立即清除 goal,UI 显示 `✕ Goal could not be achieved`,避免把循环陷死。
|
|
111
|
+
|
|
112
|
+
评估器使用 product 配置中绑定到 **`lite` 槽位**的小模型(在不同 model provider 上分别映射到 `gpt-5.1-codex-mini` / `gemini-2.5-flash` / DeepSeek `deepseek-v4-flash` 等)。评估只看现有 transcript、不调用工具,所以走小模型既快又便宜。
|
|
113
|
+
|
|
114
|
+
> **计费**:评估器消耗的 token 计在小模型账单上,相对主 turn 通常可忽略。
|
|
115
|
+
|
|
116
|
+
### 评估窗口约束
|
|
117
|
+
|
|
118
|
+
为了避免"刚 set 完就 achieved"——同一会话曾经达成过的目标会在 transcript 里留下成功响应——我们会把当前 goal 的 `createdAt`(ISO 8601)注入评估器的 user prompt,并明确指示:
|
|
119
|
+
|
|
120
|
+
> Evaluate ONLY the conversation that happened AFTER this timestamp. Earlier messages MUST NOT be used as evidence.
|
|
121
|
+
|
|
122
|
+
如果设置后还没有合格活动发生,evaluator 必须返回 `{"ok": false, "reason": "Goal was just set; no work has been done yet against the new condition."}`。
|
|
123
|
+
|
|
124
|
+
### 给 evaluator 的 history 干净化
|
|
125
|
+
|
|
126
|
+
我们会在把 history 喂给 evaluator 前过滤掉以下扩展 item type(它们是项目自定义、SDK 不认识的):
|
|
127
|
+
|
|
128
|
+
- `goal-result` / `goal-progress`(goal 自身的 UI 状态项)
|
|
129
|
+
- `summary` / `topic` / `ai-title` / `custom-title`
|
|
130
|
+
- `file-history-snapshot`
|
|
131
|
+
|
|
132
|
+
这些 item 既不是用户输入也不是 assistant 响应,对 evaluator 没有判断价值,且会触发 SDK 的 `Unknown item type` 警告。
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 实现说明与已知限制
|
|
137
|
+
|
|
138
|
+
下表汇总当前实现的关键行为与已知限制,便于排错时定位:
|
|
139
|
+
|
|
140
|
+
| 行为 | 状态 | 备注 |
|
|
141
|
+
| :--- | :--- | :--- |
|
|
142
|
+
| 设置 / 替换 / kick-off | ✅ | 设置后立即开始一轮,已有 active goal 时自动替换 |
|
|
143
|
+
| `/goal clear` 别名 | ✅ | 支持 stop / off / reset / none / cancel 五种单 token 同义词 |
|
|
144
|
+
| `/clear` 同步清除 active goal | ✅ | 重启会话时一并注销 goal hook 并清理 meta |
|
|
145
|
+
| condition 上限 | ✅ | 4000 字符 |
|
|
146
|
+
| reason 反馈进 history | ✅ | 注入格式:`Stop hook feedback: [<condition>]: <reason>` |
|
|
147
|
+
| 三态语义(ok / not-yet / impossible) | ✅ | 不可达时立即清除 goal,避免无效循环 |
|
|
148
|
+
| evaluator 走小模型 | ✅ | 使用 `lite` 槽位绑定的模型(按 provider 分别映射) |
|
|
149
|
+
| `/goal` 无参 → 状态视图 | ✅ | TUI / Web UI 面板 + headless 文本降级 |
|
|
150
|
+
| 持续运行指示器 `⊚ /goal active (Xs)` | ✅ | 输入框右下方常驻显示运行时长,1Hz 刷新 |
|
|
151
|
+
| `--resume` 时 turn / timer / token 重置 | ❌ 待补 | 当前沿用原 createdAt / turnCount,需"重新计时"请先 `/goal clear` |
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 参见
|
|
156
|
+
|
|
157
|
+
- [`/loop` 创建循环任务](./scheduled-tasks.md#使用-loop-创建循环任务):按时间间隔重复触发,而不是直到条件满足
|
|
158
|
+
- [Hook 入门](./hooks-guide.md) / [Hook 参考](./hooks.md):理解 prompt-based Stop hook 的底层机制;当你需要更复杂的评估逻辑时可以自己写一个
|
|
159
|
+
- [非交互(headless)模式](./headless.md):在 CI / 脚本中通过 `-p` 跑 `/goal`
|
|
160
|
+
- [Remote Control](./remote-control.md):在 Web UI / 微信通道中触发 goal
|
|
161
|
+
- [斜杠命令一览](./slash-commands.md):所有内置 slash 命令的索引
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Hook 参考指南
|
|
2
2
|
|
|
3
|
-
> **版本要求**:本文档针对 CodeBuddy Code v1.16.0 及以上版本中提供的
|
|
3
|
+
> **版本要求**:本文档针对 CodeBuddy Code v1.16.0 及以上版本中提供的 Hooks 实现。
|
|
4
4
|
> **功能状态**:Hook 功能当前处于 **Beta** 阶段,接口和行为可能在未来版本中调整。
|
|
5
5
|
|
|
6
|
-
Hook(钩子)允许你在 CodeBuddy Code
|
|
6
|
+
Hook(钩子)允许你在 CodeBuddy Code 的会话生命周期内插入自定义脚本或命令,实现自动化校验、环境初始化、合规检查等高级能力。
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
## 配置
|
|
@@ -142,11 +142,13 @@ Hooks 按匹配器组织,每个匹配器可以有多个 hooks:
|
|
|
142
142
|
|
|
143
143
|
> **支持的事件**:目前仅支持 `Stop`、`UserPromptSubmit` 和 `PreToolUse` 三种事件。
|
|
144
144
|
|
|
145
|
+
> **会话级捷径**:内置斜杠命令 [`/goal`](./goal.md) 是 prompt-based Stop hook 的开箱即用封装——直接输入 `/goal <condition>` 即可让 CodeBuddy 持续工作直到条件满足,无需手写 hook 配置。如果你的判定逻辑可以靠条件文本表达,优先用 `/goal`;只有需要更复杂的 prompt 编排或跨多事件协作时才回到本节自己写 prompt hook。
|
|
146
|
+
|
|
145
147
|
### 基于提示词的 hooks 如何工作
|
|
146
148
|
|
|
147
149
|
基于提示词的 hooks 不是执行 bash 命令,而是:
|
|
148
150
|
|
|
149
|
-
1. 将 hook
|
|
151
|
+
1. 将 hook 输入和你的提示词发送给快速小模型(绑定到 `lite` 槽位的小模型,按 model provider 分别映射)
|
|
150
152
|
2. LLM 使用包含决策的结构化 JSON 响应
|
|
151
153
|
3. CodeBuddy Code 自动处理决策
|
|
152
154
|
|
|
@@ -203,7 +205,8 @@ LLM 必须使用包含以下内容的 JSON 响应:
|
|
|
203
205
|
```jsonc
|
|
204
206
|
{
|
|
205
207
|
"ok": true | false,
|
|
206
|
-
"reason": "Explanation for the decision" // 当 ok 为 false 时必需
|
|
208
|
+
"reason": "Explanation for the decision", // 当 ok 为 false 时必需
|
|
209
|
+
"impossible": false // 可选,仅 Stop 事件下生效
|
|
207
210
|
}
|
|
208
211
|
```
|
|
209
212
|
|
|
@@ -211,6 +214,9 @@ LLM 必须使用包含以下内容的 JSON 响应:
|
|
|
211
214
|
|
|
212
215
|
- `ok`:`true` 允许操作,`false` 阻止操作
|
|
213
216
|
- `reason`:当 `ok` 为 `false` 时必需,显示给 CodeBuddy 的解释
|
|
217
|
+
- `impossible`:可选布尔值,仅 `Stop` hook 下有意义。`{ok: false, impossible: true}` 表示评估器判断"在当前会话里这个目标根本不可能完成"(条件自相矛盾、依赖资源不可用、模型已穷尽合理尝试)。CodeBuddy 不再继续循环,UI 显示"无法达成"终态。普通 `{ok: false}` 仍按"未达成、继续工作"处理。
|
|
218
|
+
|
|
219
|
+
**reason 注入 history 的语义**:`Stop` hook 返回 `{ok: false}` 时,`reason` 文本不是简单地"显示给 CodeBuddy"——它会以 `isMeta=true` 的内部 user message 形式注入到对话 history 中,让主模型在下一轮看到评估器的视角,从而精准补做欠缺的部分。这是 prompt-based Stop hook 能驱动多轮迭代收敛的核心机制(`/goal` 命令底层就是依赖这条链路)。
|
|
214
220
|
|
|
215
221
|
### 示例:智能 Stop Hook
|
|
216
222
|
|
|
@@ -362,6 +368,8 @@ LLM 必须使用包含以下内容的 JSON 响应:
|
|
|
362
368
|
|
|
363
369
|
在主 CodeBuddy Code 代理完成响应时运行。如果停止是由于用户中断而发生的,则不会运行。
|
|
364
370
|
|
|
371
|
+
> **会话级捷径**:内置斜杠命令 [`/goal`](./goal.md) 是 session-scoped prompt-based Stop hook 的封装——`/goal <condition>` 一行即可注册一个让 CodeBuddy 持续工作到条件满足为止的 Stop hook,并自动处理三态评估(达成 / 未达成继续 / 不可达成)、turn 计数、token 统计、`/resume` 自动恢复等细节。需要会话级"持续工作直到 X"时优先考虑 `/goal`,不必手写 hook 配置。
|
|
372
|
+
|
|
365
373
|
### SubagentStop
|
|
366
374
|
|
|
367
375
|
在 CodeBuddy Code 子代理(Agent 工具调用)完成响应时运行。
|
|
@@ -17,6 +17,8 @@ Release Notes 记录了每个版本的用户可见变更,包括:
|
|
|
17
17
|
|
|
18
18
|
<!-- 新版本自动添加到此处 -->
|
|
19
19
|
|
|
20
|
+
- [v2.98.1](./v2.98.1.md) - 2026-05-25
|
|
21
|
+
- [v2.98.0](./v2.98.0.md) - 2026-05-24
|
|
20
22
|
- [v2.97.5](./v2.97.5.md) - 2026-05-22
|
|
21
23
|
- [v2.97.4](./v2.97.4.md) - 2026-05-21
|
|
22
24
|
- [v2.97.3](./v2.97.3.md) - 2026-05-19
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# 🚀 CodeBuddy Code v2.98.0 发布
|
|
2
|
+
|
|
3
|
+
## 📦 版本信息
|
|
4
|
+
|
|
5
|
+
| 组件 | 版本 |
|
|
6
|
+
|------|------|
|
|
7
|
+
| CodeBuddy Code CLI | v2.98.0 |
|
|
8
|
+
| Agent SDK JS | v0.3.156 |
|
|
9
|
+
| Agent SDK Python | v0.3.155 |
|
|
10
|
+
|
|
11
|
+
## ✨ 新功能
|
|
12
|
+
|
|
13
|
+
### OpenTelemetry 自定义上报(traces)
|
|
14
|
+
|
|
15
|
+
支持通过 OTel 标准环境变量将内部 traces 上报到自有 Collector,便于和企业可观测平台集成:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
export CODEBUDDY_CODE_ENABLE_TELEMETRY=1
|
|
19
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT=https://otel.corp.example.com
|
|
20
|
+
export OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer%20<TOKEN>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
支持 `OTEL_TRACES_EXPORTER` / `OTEL_SERVICE_NAME` / `OTEL_RESOURCE_ATTRIBUTES` 等标准变量。详见 `docs/monitoring.md`。
|
|
24
|
+
|
|
25
|
+
### 沙箱生态资产目录白名单
|
|
26
|
+
|
|
27
|
+
沙箱安全策略默认允许 WorkBuddy 生态资产目录和跨平台技能目录写入,减少插件、技能与连接器在沙箱环境中的访问受限问题。
|
|
28
|
+
|
|
29
|
+
## 🔧 改进优化
|
|
30
|
+
|
|
31
|
+
- **自动压缩窗口提升**:未配置 `maxInputTokens` 的模型,默认 auto-compact 窗口从 100k 提升到 200k token
|
|
32
|
+
- **Hooks 注入 agent_id / agent_type**:所有 hook 事件 payload 补齐触发源标识,方便在全局 hook 里区分主会话与子 agent
|
|
33
|
+
- **Hook 去重精细化**:解决"同事件触发两次"问题,settings 跨 scope 同一 command 折叠成一份,不同插件 / 子 agent scope 各自保留一份
|
|
34
|
+
- **多源 hook 命中可观测**:同一事件命中 ≥ 2 条不同 hook 时,日志列出所有命中命令,方便自查冲突
|
|
35
|
+
- **CLI 文档补齐**:新增 `monitoring.md` 与 `codebuddy-dir.md`,完成 v2.96.1 ~ v2.97.5 release notes 中英文同步与导航更新
|
|
36
|
+
|
|
37
|
+
## 🐛 问题修复
|
|
38
|
+
|
|
39
|
+
- **后台 Bash 僵尸进程**:修复 `nohup` 等后台命令残留僵尸进程。stdout/stderr 改为直接写文件 fd;新增 50MB 输出看门狗(`CODEBUDDY_BASH_BG_MAX_OUTPUT_BYTES` 可调)和 `CODEBUDDY_BASH_BG_PIPE_MODE=1` 回滚开关
|
|
40
|
+
- **官方 Copilot 网关保留 thinking 字段**:修复 `auto` 模型开启思考后,请求发往官方网关时 thinking 字段被过早清理的问题
|
|
41
|
+
- **压缩类型透传**:修复自动压缩与手动 `/compact` 在 ACP `_meta` 中无法区分的问题
|
|
42
|
+
- **进程终止可靠性**:修复 `dispose()` 后 `kill()` 被 `_disposed` 标志拦截、以及 `disposeAll()` exit 事件路由丢失的问题
|
|
43
|
+
|
|
44
|
+
## 📝 文档更新
|
|
45
|
+
|
|
46
|
+
- **CLI 监控文档**:新增 `monitoring.md` 介绍 OpenTelemetry 自定义上报
|
|
47
|
+
- **目录结构说明**:新增 `codebuddy-dir.md` 说明 `~/.codebuddy/` 与 `.codebuddy/` 目录结构、配置优先级与记忆加载顺序
|
|
48
|
+
- **Release Notes 索引**:补齐 v2.96.1 ~ v2.97.5 共 7 个版本的中英文 release notes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# 🚀 CodeBuddy Code v2.98.1 发布
|
|
2
|
+
|
|
3
|
+
## 📦 版本信息
|
|
4
|
+
|
|
5
|
+
| 组件 | 版本 |
|
|
6
|
+
|------|------|
|
|
7
|
+
| CodeBuddy Code CLI | v2.98.1 |
|
|
8
|
+
| Agent SDK JS | v0.3.157 |
|
|
9
|
+
| Agent SDK Python | v0.3.156 |
|
|
10
|
+
|
|
11
|
+
## 📌 概述
|
|
12
|
+
|
|
13
|
+
v2.98.0 因发版流水线 OOM 未能成功发布到 npm,本次以 v2.98.1 补发。**功能与 v2.98.0 完全等价**,所有 v2.98.0 的新功能、改进与修复均包含在本版本中。如果你已尝试安装 v2.98.0 失败,请直接升级到 v2.98.1。
|
|
14
|
+
|
|
15
|
+
完整变更详情请参考 [v2.98.0 发布说明](./v2.98.0.md)。
|
|
16
|
+
|
|
17
|
+
## 🐛 问题修复
|
|
18
|
+
|
|
19
|
+
- **修复 agent-cli 正式发版流水线 OOM**:调高发版构建阶段 Node 堆内存上限至 8GB,解决 v2.98.0 在 `yarn build` 阶段被 OOM Killer 终止、导致 npm 包未能发布的问题,让后续版本能够稳定发布。
|
|
@@ -30,6 +30,7 @@ CodeBuddy Code 支持斜杠命令,允许您在聊天中执行特殊操作、
|
|
|
30
30
|
| `/model:image-to-image` | `[list \| model-id]` | ✅ 支持 | 切换或查看当前使用的图生图模型。不带参数时打开交互式选择界面,`list` 列出可用模型,带模型 ID 参数时直接切换到指定模型。 |
|
|
31
31
|
| `/permissions` | | ✅ 支持 | 管理工具权限和工作区目录访问权限。 |
|
|
32
32
|
| `/plan` | | ✅ 支持 | 预览当前计划模式下的计划文件内容。 |
|
|
33
|
+
| `/goal` | `<condition> \| clear` | ✅ 支持 | 持续工作直到达成条件。`/goal <condition>` 设定一个目标条件(例:`/goal all tests pass`),会话级注册一个 prompt 类型的 Stop hook,模型每次想停下来时由小模型评估器判断条件是否满足;不满足则把 reason 注入 history 让模型继续工作。`/goal` 不带参数打开 recap 面板,`/goal clear`(别名:`stop` / `off` / `reset` / `none` / `cancel`)提前结束目标。详见 [goal 文档](./goal.md)。 |
|
|
33
34
|
| `/upgrade` | | ✅ 支持 | 在浏览器中打开升级页面,查看高级功能和订阅选项。 |
|
|
34
35
|
| `/bashes` | | ✅ 支持 | 列出和管理后台任务。 |
|
|
35
36
|
| `/terminal-setup` | | ✅ 支持 | 配置 Shift+Enter 快捷键绑定,用于在输入框中插入换行符。 |
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Keep CodeBuddy Working Until a Goal Is Met
|
|
2
|
+
|
|
3
|
+
> Use `/goal` to set a completion condition. CodeBuddy will keep working across multiple turns until the condition is satisfied before handing control back to you.
|
|
4
|
+
|
|
5
|
+
> **Version requirement**: The `/goal` command requires `@tencent-ai/codebuddy-code` with the goal feature included (the `GoalService` module in agent-cli).
|
|
6
|
+
|
|
7
|
+
`/goal` sets a completion condition that CodeBuddy continuously works toward without you prompting it step by step. At the end of each turn, a small-fast model evaluator checks whether the condition holds — if not, CodeBuddy automatically starts the next turn rather than returning control to you. Once the condition is met, the goal is automatically cleared.
|
|
8
|
+
|
|
9
|
+
`/goal` is suitable for tracking substantial work that has a verifiable end state:
|
|
10
|
+
|
|
11
|
+
- Migrating a module to a new API until all call sites compile and tests pass
|
|
12
|
+
- Implementing a design doc until all acceptance criteria are met
|
|
13
|
+
- Splitting a large file into focused modules until each one is within the size budget
|
|
14
|
+
- Processing a list of issues with a certain label until the queue is empty
|
|
15
|
+
|
|
16
|
+
This document covers:
|
|
17
|
+
|
|
18
|
+
- [Comparison with other autonomous workflows](#comparison-with-other-autonomous-workflows): choosing between `/goal`, `/loop`, and Stop hooks
|
|
19
|
+
- [Setting a goal](#setting-a-goal) and [tips for writing effective conditions](#writing-an-effective-condition)
|
|
20
|
+
- [Checking status](#checking-status), [clearing early](#clearing-a-goal-early), [running in non-interactive mode](#running-in-non-interactive-mode)
|
|
21
|
+
- [How the evaluator works](#how-the-evaluator-works)
|
|
22
|
+
- [Implementation notes and known limitations](#implementation-notes-and-known-limitations)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## Using `/goal`
|
|
26
|
+
|
|
27
|
+
Each session can only have one active goal at a time. The same command takes on the role of "set / view / clear" depending on the arguments.
|
|
28
|
+
|
|
29
|
+
### Setting a Goal
|
|
30
|
+
|
|
31
|
+
Follow `/goal` with the condition you want to satisfy. If there is already an active goal, the new one replaces it (the old goal's hook is automatically unregistered).
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
/goal all tests in test/auth pass and the lint step is clean
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Once set, CodeBuddy **immediately starts a turn**, passing "the condition itself" as the instruction to the main agent — you don't need to send an additional prompt. A `⊚ /goal active (Xs)` indicator also appears at the bottom-right of the input box, refreshing every second with the elapsed time, so you always know when goal mode is active.
|
|
38
|
+
|
|
39
|
+
After each turn, the evaluator returns a short reason explaining "why the condition is / is not yet met." This reason is injected into the conversation history as an `isMeta=true` internal message, allowing the model to see the evaluator's perspective on the next turn and precisely address what is missing — this is the key mechanism for the model to "know what steps remain."
|
|
40
|
+
|
|
41
|
+
> **Session-level behavior**: The goal keeps running until the condition is met or you run `/goal clear`. Run `/goal` (no arguments) to see stats like turns and tokens.
|
|
42
|
+
|
|
43
|
+
### Writing an Effective Condition
|
|
44
|
+
|
|
45
|
+
The [evaluator](#how-the-evaluator-works) judges the condition based solely on what CodeBuddy has **already expressed** in the conversation — it does not run commands or read files itself. So the condition should be phrased in a form that "CodeBuddy's own output can prove." "All tests in `test/auth` pass" works because CodeBuddy will run the tests itself, and the results will be in the transcript for the evaluator to read.
|
|
46
|
+
|
|
47
|
+
A condition that robustly supports multi-turn work typically includes:
|
|
48
|
+
|
|
49
|
+
- **A measurable end state**: test results, build exit codes, file counts, an empty queue…
|
|
50
|
+
- **A provable method**: e.g., ``\`npm test\` exits 0`` or ``\`git status\` is clean``
|
|
51
|
+
- **Inviolable constraints**: things that must not be changed along the way, e.g., "no other test file is modified"
|
|
52
|
+
|
|
53
|
+
The condition length limit is **4000 characters**.
|
|
54
|
+
|
|
55
|
+
If you want to set a fallback upper bound for the goal, add a turn/time clause to the condition, e.g., `or stop after 20 turns`. CodeBuddy will check progress against this clause each turn, and the evaluator can also read it from the conversation.
|
|
56
|
+
|
|
57
|
+
### Checking Status
|
|
58
|
+
|
|
59
|
+
Run `/goal` without arguments:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
/goal
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
In the TUI this opens a goal recap panel; in Web UI / ACP clients it opens an equivalent panel via ACP broadcast; in headless / SDK environments without a UI it falls back to plain text output.
|
|
66
|
+
|
|
67
|
+
Panel contents include:
|
|
68
|
+
- The condition
|
|
69
|
+
- Elapsed time
|
|
70
|
+
- Number of evaluated turns
|
|
71
|
+
- Token consumption (incremental during goal)
|
|
72
|
+
- The most recent reason from the evaluator
|
|
73
|
+
|
|
74
|
+
If there is no active goal but a goal was previously achieved in this session, the panel shows that goal's condition, duration, turn count, and token count.
|
|
75
|
+
|
|
76
|
+
### Clearing a Goal Early
|
|
77
|
+
|
|
78
|
+
```text
|
|
79
|
+
/goal clear
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The following tokens are all treated as synonyms for `clear`: `stop`, `off`, `reset`, `none`, `cancel`. These are only recognized as clear commands on **exact single-token match** — `/goal stop using deprecated API` is still treated as "set a new condition" and won't be consumed.
|
|
83
|
+
|
|
84
|
+
Running `/clear` to restart the session also removes the active goal (hook unregistered + meta cleaned up).
|
|
85
|
+
|
|
86
|
+
### Resuming a Session with a Goal
|
|
87
|
+
|
|
88
|
+
When resuming a session via `--resume` / `--continue`, an unfinished goal is restored (both condition and scope are preserved).
|
|
89
|
+
|
|
90
|
+
> **Current limitation**: On resume, the original goal's createdAt / turnCount / token starting point are carried over — the timer and counters are not reset. If you want to "restart the clock," first run `/goal clear` and then `/goal <condition>` again. Goals that were already achieved or cleared will not be restored (meta has been deleted).
|
|
91
|
+
|
|
92
|
+
### Running in Non-Interactive Mode
|
|
93
|
+
|
|
94
|
+
`/goal` works in [non-interactive (headless) mode](./headless.md) and [Remote Control](./remote-control.md). In `-p` mode, setting a goal causes the evaluator loop to run until completion:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
codebuddy -p "/goal CHANGELOG.md has an entry for every PR merged this week"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
To terminate early before the condition is met, press `Ctrl+C`.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## How the Evaluator Works
|
|
105
|
+
|
|
106
|
+
`/goal` is a wrapper around a session-level [prompt-based Stop hook](./hooks.md). Whenever CodeBuddy's main agent finishes a turn, **the current condition + the current conversation** are sent together to the configured small-model evaluator. The evaluator returns a three-state result (yes / no / unreachable) with a short reason:
|
|
107
|
+
|
|
108
|
+
- **Yes (`ok: true`)**: Clears the goal, logs an "achieved" event, and the UI shows a `✔ Goal achieved` status bar.
|
|
109
|
+
- **No (`ok: false`)**: Injects the reason as an `isMeta=true` user message into the history (so the main model sees what to work on next), and lets CodeBuddy continue working. Also writes a `goal-progress` UI status bar: `◯ Goal not yet met… continuing`.
|
|
110
|
+
- **Unreachable (`ok: false, impossible: true`)**: Used when the evaluator determines that "this goal simply cannot be completed in the current session" (the condition is self-contradictory, required capabilities/resources are unavailable, or the model has exhausted reasonable attempts). The goal is immediately cleared, and the UI shows `✕ Goal could not be achieved`, preventing the loop from getting stuck.
|
|
111
|
+
|
|
112
|
+
The evaluator uses the small model bound to the **`lite` slot** in the product configuration (mapped to `gpt-5.1-codex-mini` / `gemini-2.5-flash` / DeepSeek `deepseek-v4-flash` etc. depending on the model provider). Evaluation only reads the existing transcript without invoking tools, so using a small model is both fast and cheap.
|
|
113
|
+
|
|
114
|
+
> **Billing**: Tokens consumed by the evaluator are billed to the small model account and are typically negligible compared to the main turn.
|
|
115
|
+
|
|
116
|
+
### Evaluation Window Constraint
|
|
117
|
+
|
|
118
|
+
To prevent "achieved immediately after setting" — where a previously achieved goal in the same session leaves a success response in the transcript — we inject the current goal's `createdAt` (ISO 8601) into the evaluator's user prompt with an explicit instruction:
|
|
119
|
+
|
|
120
|
+
> Evaluate ONLY the conversation that happened AFTER this timestamp. Earlier messages MUST NOT be used as evidence.
|
|
121
|
+
|
|
122
|
+
If no qualifying activity has occurred since the goal was set, the evaluator must return `{"ok": false, "reason": "Goal was just set; no work has been done yet against the new condition."}`.
|
|
123
|
+
|
|
124
|
+
### History Sanitization for the Evaluator
|
|
125
|
+
|
|
126
|
+
Before feeding history to the evaluator, we filter out the following extended item types (they are project-specific and unrecognized by the SDK):
|
|
127
|
+
|
|
128
|
+
- `goal-result` / `goal-progress` (goal's own UI status items)
|
|
129
|
+
- `summary` / `topic` / `ai-title` / `custom-title`
|
|
130
|
+
- `file-history-snapshot`
|
|
131
|
+
|
|
132
|
+
These items are neither user input nor assistant responses, have no value for the evaluator's judgment, and would trigger `Unknown item type` warnings from the SDK.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Implementation Notes and Known Limitations
|
|
137
|
+
|
|
138
|
+
The following table summarizes key behaviors and known limitations of the current implementation for debugging reference:
|
|
139
|
+
|
|
140
|
+
| Behavior | Status | Notes |
|
|
141
|
+
| :--- | :--- | :--- |
|
|
142
|
+
| Set / replace / kick-off | ✅ | Immediately starts a turn after setting; auto-replaces when there's already an active goal |
|
|
143
|
+
| `/goal clear` aliases | ✅ | Supports five single-token synonyms: stop / off / reset / none / cancel |
|
|
144
|
+
| `/clear` also clears active goal | ✅ | Unregisters goal hook and cleans meta on session restart |
|
|
145
|
+
| Condition limit | ✅ | 4000 characters |
|
|
146
|
+
| Reason feedback into history | ✅ | Injection format: `Stop hook feedback: [<condition>]: <reason>` |
|
|
147
|
+
| Three-state semantics (ok / not-yet / impossible) | ✅ | Immediately clears goal on unreachable, preventing infinite loops |
|
|
148
|
+
| Evaluator uses small model | ✅ | Uses the model bound to `lite` slot (mapped per provider) |
|
|
149
|
+
| `/goal` no-arg → status view | ✅ | TUI / Web UI panel + headless text fallback |
|
|
150
|
+
| Persistent running indicator `⊚ /goal active (Xs)` | ✅ | Always visible at bottom-right of input box, 1Hz refresh |
|
|
151
|
+
| `--resume` turn / timer / token reset | ❌ Pending | Currently carries over original createdAt / turnCount; use `/goal clear` + re-set to restart |
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## See Also
|
|
156
|
+
|
|
157
|
+
- [`/loop` for scheduled tasks](./scheduled-tasks.md#使用-loop-创建循环任务): Triggers repeatedly on a time interval, rather than until a condition is met
|
|
158
|
+
- [Hooks Guide](./hooks-guide.md) / [Hooks Reference](./hooks.md): Understand the underlying mechanism of prompt-based Stop hooks; write your own when you need more complex evaluation logic
|
|
159
|
+
- [Non-interactive (headless) mode](./headless.md): Run `/goal` in CI / scripts via `-p`
|
|
160
|
+
- [Remote Control](./remote-control.md): Trigger goals in Web UI / WeChat channels
|
|
161
|
+
- [Slash Commands Overview](./slash-commands.md): Index of all built-in slash commands
|
|
@@ -142,11 +142,13 @@ Besides shell commands (`type: "command"`), CodeBuddy Code also supports prompt-
|
|
|
142
142
|
|
|
143
143
|
> **Supported events**: Currently only `Stop`, `UserPromptSubmit`, and `PreToolUse` events are supported.
|
|
144
144
|
|
|
145
|
+
> **Session-level shortcut**: The built-in slash command [`/goal`](./goal.md) is a ready-to-use wrapper around prompt-based Stop hooks — simply type `/goal <condition>` to have CodeBuddy keep working until the condition is met, without writing hook configuration manually. If your evaluation logic can be expressed as a condition string, prefer `/goal`; only fall back to writing your own prompt hook when you need more complex prompt orchestration or cross-event coordination.
|
|
146
|
+
|
|
145
147
|
### How Prompt Hooks Work
|
|
146
148
|
|
|
147
149
|
Instead of running a bash command, the hook:
|
|
148
150
|
|
|
149
|
-
1. Sends the hook input plus your prompt to a fast
|
|
151
|
+
1. Sends the hook input plus your prompt to a fast small model (bound to the `lite` slot, mapped per model provider).
|
|
150
152
|
2. Receives a structured JSON decision.
|
|
151
153
|
3. Lets CodeBuddy Code enforce that decision.
|
|
152
154
|
|
|
@@ -201,7 +203,8 @@ The LLM must return JSON:
|
|
|
201
203
|
```jsonc
|
|
202
204
|
{
|
|
203
205
|
"ok": true | false,
|
|
204
|
-
"reason": "Explanation for the decision" // Required when ok is false
|
|
206
|
+
"reason": "Explanation for the decision", // Required when ok is false
|
|
207
|
+
"impossible": false // Optional, only effective for Stop events
|
|
205
208
|
}
|
|
206
209
|
```
|
|
207
210
|
|
|
@@ -209,6 +212,9 @@ The LLM must return JSON:
|
|
|
209
212
|
|
|
210
213
|
- `ok`: `true` to allow the operation, `false` to block it
|
|
211
214
|
- `reason`: Required when `ok` is `false`, explanation shown to CodeBuddy
|
|
215
|
+
- `impossible`: Optional boolean, only meaningful for `Stop` hooks. `{ok: false, impossible: true}` indicates that the evaluator has determined "this goal is fundamentally impossible to achieve within the current session" (contradictory conditions, unavailable resources, or the model has exhausted all reasonable attempts). CodeBuddy will stop looping and the UI displays a "cannot be achieved" terminal state. A plain `{ok: false}` still means "not yet achieved, keep working".
|
|
216
|
+
|
|
217
|
+
**`reason` injection into history semantics**: When a `Stop` hook returns `{ok: false}`, the `reason` text is not simply "shown to CodeBuddy" — it is injected as an internal user message with `isMeta=true` into the conversation history, so that the main model sees the evaluator's perspective in the next turn and can precisely address the outstanding gaps. This is the core mechanism that allows prompt-based Stop hooks to drive multi-turn iterative convergence (the `/goal` command relies on this pipeline under the hood).
|
|
212
218
|
|
|
213
219
|
### Example: Smart Stop Hook
|
|
214
220
|
|
|
@@ -360,6 +366,8 @@ Runs after the user submits a prompt but before CodeBuddy processes it. Useful f
|
|
|
360
366
|
|
|
361
367
|
Runs when the primary CodeBuddy agent finishes responding (skipped if the user manually interrupts).
|
|
362
368
|
|
|
369
|
+
> **Session-level shortcut**: The built-in slash command [`/goal`](./goal.md) is a wrapper around session-scoped prompt-based Stop hooks — `/goal <condition>` is all it takes to register a Stop hook that keeps CodeBuddy working until the condition is met, automatically handling three-state evaluation (achieved / not yet achieved, keep working / impossible to achieve), turn counting, token statistics, and `/resume` auto-recovery. When you need a session-level "keep working until X" behavior, prefer `/goal` instead of writing hook configuration manually.
|
|
370
|
+
|
|
363
371
|
### SubagentStop
|
|
364
372
|
|
|
365
373
|
Runs when a CodeBuddy sub-agent (Task tool) finishes.
|
|
@@ -17,6 +17,8 @@ Difference from CHANGELOG.md:
|
|
|
17
17
|
|
|
18
18
|
<!-- New versions are automatically added here -->
|
|
19
19
|
|
|
20
|
+
- [v2.98.1](./v2.98.1.md) - 2026-05-25
|
|
21
|
+
- [v2.98.0](./v2.98.0.md) - 2026-05-24
|
|
20
22
|
- [v2.97.5](./v2.97.5.md) - 2026-05-22
|
|
21
23
|
- [v2.97.4](./v2.97.4.md) - 2026-05-21
|
|
22
24
|
- [v2.97.3](./v2.97.3.md) - 2026-05-19
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# 🚀 CodeBuddy Code v2.98.0 Release
|
|
2
|
+
|
|
3
|
+
## 📦 Version Info
|
|
4
|
+
|
|
5
|
+
| Component | Version |
|
|
6
|
+
|------|------|
|
|
7
|
+
| CodeBuddy Code CLI | v2.98.0 |
|
|
8
|
+
| Agent SDK JS | v0.3.156 |
|
|
9
|
+
| Agent SDK Python | v0.3.155 |
|
|
10
|
+
|
|
11
|
+
## ✨ New Features
|
|
12
|
+
|
|
13
|
+
### OpenTelemetry Custom Reporting (Traces)
|
|
14
|
+
|
|
15
|
+
Support exporting internal traces to your own Collector via standard OTel environment variables, enabling integration with enterprise observability platforms:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
export CODEBUDDY_CODE_ENABLE_TELEMETRY=1
|
|
19
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT=https://otel.corp.example.com
|
|
20
|
+
export OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer%20<TOKEN>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Supports standard variables such as `OTEL_TRACES_EXPORTER` / `OTEL_SERVICE_NAME` / `OTEL_RESOURCE_ATTRIBUTES`. See `docs/monitoring.md` for details.
|
|
24
|
+
|
|
25
|
+
### Sandbox Ecosystem Asset Directory Allowlist
|
|
26
|
+
|
|
27
|
+
The sandbox security policy now allows write access to WorkBuddy ecosystem asset directories and cross-platform skill directories by default, reducing access restriction issues for plugins, skills, and connectors in sandbox environments.
|
|
28
|
+
|
|
29
|
+
## 🔧 Improvements
|
|
30
|
+
|
|
31
|
+
- **Auto-compact window increase**: For models without `maxInputTokens` configured, the default auto-compact window has been raised from 100k to 200k tokens
|
|
32
|
+
- **Hooks inject agent_id / agent_type**: All hook event payloads now include trigger source identifiers, making it easier to distinguish between main sessions and sub-agents in global hooks
|
|
33
|
+
- **Hook deduplication refinement**: Resolved "same event triggered twice" issue — same command across settings scopes is collapsed into one, while different plugin/sub-agent scopes each retain their own copy
|
|
34
|
+
- **Multi-source hook hit observability**: When a single event matches ≥ 2 different hooks, logs now list all matched commands for easier conflict debugging
|
|
35
|
+
- **CLI documentation updates**: Added `monitoring.md` and `codebuddy-dir.md`, completed v2.96.1 ~ v2.97.5 release notes bilingual sync and navigation updates
|
|
36
|
+
|
|
37
|
+
## 🐛 Bug Fixes
|
|
38
|
+
|
|
39
|
+
- **Background Bash zombie processes**: Fixed zombie processes left by background commands like `nohup`. stdout/stderr now write directly to file descriptors; added 50MB output watchdog (`CODEBUDDY_BASH_BG_MAX_OUTPUT_BYTES` configurable) and `CODEBUDDY_BASH_BG_PIPE_MODE=1` rollback switch
|
|
40
|
+
- **Official Copilot gateway retains thinking field**: Fixed an issue where the thinking field was prematurely cleared when requests with `auto` model thinking enabled were sent to the official gateway
|
|
41
|
+
- **Compact type passthrough**: Fixed an issue where auto-compact and manual `/compact` could not be distinguished in ACP `_meta`
|
|
42
|
+
- **Process termination reliability**: Fixed issues where `kill()` was blocked by `_disposed` flag after `dispose()`, and `disposeAll()` exit event routing was lost
|
|
43
|
+
|
|
44
|
+
## 📝 Documentation Updates
|
|
45
|
+
|
|
46
|
+
- **CLI Monitoring Documentation**: Added `monitoring.md` covering OpenTelemetry custom reporting
|
|
47
|
+
- **Directory Structure Guide**: Added `codebuddy-dir.md` explaining `~/.codebuddy/` and `.codebuddy/` directory structure, configuration priority, and memory loading order
|
|
48
|
+
- **Release Notes Index**: Added bilingual release notes for 7 versions from v2.96.1 ~ v2.97.5
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# 🚀 CodeBuddy Code v2.98.1 Release
|
|
2
|
+
|
|
3
|
+
## 📦 Version Info
|
|
4
|
+
|
|
5
|
+
| Component | Version |
|
|
6
|
+
|------|------|
|
|
7
|
+
| CodeBuddy Code CLI | v2.98.1 |
|
|
8
|
+
| Agent SDK JS | v0.3.157 |
|
|
9
|
+
| Agent SDK Python | v0.3.156 |
|
|
10
|
+
|
|
11
|
+
## 📌 Overview
|
|
12
|
+
|
|
13
|
+
v2.98.0 failed to publish to npm due to an OOM issue in the release pipeline. This version is a re-release as v2.98.1. **It is functionally identical to v2.98.0** — all new features, improvements, and fixes from v2.98.0 are included in this version. If you previously attempted to install v2.98.0 and it failed, please upgrade directly to v2.98.1.
|
|
14
|
+
|
|
15
|
+
For full change details, refer to the [v2.98.0 Release Notes](./v2.98.0.md).
|
|
16
|
+
|
|
17
|
+
## 🐛 Bug Fixes
|
|
18
|
+
|
|
19
|
+
- **Fix agent-cli release pipeline OOM**: Increased the Node heap memory limit to 8GB during the release build stage, resolving the issue where v2.98.0 was terminated by the OOM Killer during `yarn build`, preventing the npm package from being published, and ensuring stable publishing for subsequent versions.
|
|
@@ -30,6 +30,7 @@ These commands are used to manage your CodeBuddy Code sessions. Here is the curr
|
|
|
30
30
|
| `/model:image-to-image` | `[list \| model-id]` | ✅ Supported | Switch or view the currently used image-to-image model. Opens an interactive selection interface when used without parameters, `list` lists available models, or directly switches to the specified model when provided with a model ID. |
|
|
31
31
|
| `/permissions` | | ✅ Supported | Manage tool permissions and workspace directory access permissions. |
|
|
32
32
|
| `/plan` | | ✅ Supported | Preview the plan file content in the current plan mode. |
|
|
33
|
+
| `/goal` | `<condition> \| clear` | ✅ Supported | Keep working until a condition is met. `/goal <condition>` sets a goal condition (e.g., `/goal all tests pass`), registering a session-level prompt-based Stop hook. Each time the model wants to stop, a small-model evaluator checks whether the condition is satisfied; if not, it injects the reason into history so the model continues working. `/goal` without arguments opens the recap panel. `/goal clear` (aliases: `stop` / `off` / `reset` / `none` / `cancel`) ends the goal early. See [Goal Documentation](./goal.md). |
|
|
33
34
|
| `/upgrade` | | ✅ Supported | Open the upgrade page in your browser to view premium features and subscription options. |
|
|
34
35
|
| `/bashes` | | ✅ Supported | List and manage background tasks. |
|
|
35
36
|
| `/terminal-setup` | | ✅ Supported | Configure Shift+Enter keyboard shortcut binding for inserting line breaks in the input box. |
|