@foxden-app/foxclaw 0.5.53 → 0.5.54
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/CHANGELOG.md +12 -0
- package/dist/controller/activity.js +88 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable FoxClaw changes are listed here. Each release note is bilingual so GitHub Releases and the npm package are useful to both Chinese and English readers.
|
|
4
4
|
|
|
5
|
+
## 0.5.54 - 2026-06-20
|
|
6
|
+
|
|
7
|
+
### 中文
|
|
8
|
+
- 修复升级到 Codex CLI `0.141.0` 后 Telegram 看不到工具执行明细的问题;FoxClaw 现在支持现代 app-server 的 `item/started` / `item/completed` 工具生命周期。
|
|
9
|
+
- 命令执行、文件修改、网页搜索、MCP/动态工具、图片查看和生成、协作 Agent 操作会重新实时显示;阶段结束后仍压缩为可展开明细,最终过程汇报继续独立折叠。
|
|
10
|
+
- 保留旧版 `codex/event/exec_command_begin/end` 兼容,避免旧节点或旧 Codex CLI 失去过程状态。
|
|
11
|
+
|
|
12
|
+
### English
|
|
13
|
+
- Fixed Telegram tool activity details disappearing after upgrading to Codex CLI `0.141.0`; FoxClaw now supports the modern app-server `item/started` and `item/completed` tool lifecycle.
|
|
14
|
+
- Command execution, file changes, web search, MCP/dynamic tools, image activity, and collaborative agent operations are visible in real time again, then archived into expandable stage details.
|
|
15
|
+
- Kept compatibility with legacy `codex/event/exec_command_begin/end` notifications for older Codex CLI installations.
|
|
16
|
+
|
|
5
17
|
## 0.5.53 - 2026-06-20
|
|
6
18
|
|
|
7
19
|
### 中文
|
|
@@ -52,6 +52,10 @@ function normalizeStartedEvent(params) {
|
|
|
52
52
|
state: 'thinking',
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
|
+
const toolEvent = normalizeThreadItemToolEvent(params, 'tool_started');
|
|
56
|
+
if (toolEvent) {
|
|
57
|
+
return toolEvent;
|
|
58
|
+
}
|
|
55
59
|
if (!isRelayableTextItemType(itemType)) {
|
|
56
60
|
return null;
|
|
57
61
|
}
|
|
@@ -113,6 +117,10 @@ function normalizeCompletedEvent(params) {
|
|
|
113
117
|
state: 'thinking',
|
|
114
118
|
};
|
|
115
119
|
}
|
|
120
|
+
const toolEvent = normalizeThreadItemToolEvent(params, 'tool_completed');
|
|
121
|
+
if (toolEvent) {
|
|
122
|
+
return toolEvent;
|
|
123
|
+
}
|
|
116
124
|
if (!isRelayableTextItemType(itemType)) {
|
|
117
125
|
return null;
|
|
118
126
|
}
|
|
@@ -161,6 +169,86 @@ function normalizeToolEvent(params, kind) {
|
|
|
161
169
|
state: inferToolActivityState(exec),
|
|
162
170
|
};
|
|
163
171
|
}
|
|
172
|
+
function normalizeThreadItemToolEvent(params, kind) {
|
|
173
|
+
const turnId = extractTurnId(params);
|
|
174
|
+
const item = params?.item;
|
|
175
|
+
const itemId = extractItemId(item);
|
|
176
|
+
const itemType = normalizeEventItemType(item);
|
|
177
|
+
if (!turnId || !itemId || !itemType) {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
let command = [];
|
|
181
|
+
let cwd = null;
|
|
182
|
+
let parsedCmd = [];
|
|
183
|
+
switch (itemType) {
|
|
184
|
+
case 'commandexecution':
|
|
185
|
+
command = typeof item.command === 'string' ? [item.command] : [];
|
|
186
|
+
cwd = typeof item.cwd === 'string' ? item.cwd : null;
|
|
187
|
+
parsedCmd = normalizeCommandActions(item.commandActions);
|
|
188
|
+
break;
|
|
189
|
+
case 'filechange':
|
|
190
|
+
parsedCmd = normalizeFileChanges(item.changes);
|
|
191
|
+
break;
|
|
192
|
+
case 'websearch':
|
|
193
|
+
parsedCmd = [{
|
|
194
|
+
type: 'search',
|
|
195
|
+
query: typeof item.query === 'string' ? item.query : '',
|
|
196
|
+
path: null,
|
|
197
|
+
}];
|
|
198
|
+
break;
|
|
199
|
+
case 'imageview':
|
|
200
|
+
parsedCmd = [{ type: 'read', path: typeof item.path === 'string' ? item.path : null }];
|
|
201
|
+
break;
|
|
202
|
+
case 'mcptoolcall':
|
|
203
|
+
command = [`MCP ${String(item.server ?? 'server')}/${String(item.tool ?? 'tool')}`];
|
|
204
|
+
break;
|
|
205
|
+
case 'dynamictoolcall':
|
|
206
|
+
command = [`Tool ${item.namespace ? `${String(item.namespace)}/` : ''}${String(item.tool ?? 'tool')}`];
|
|
207
|
+
break;
|
|
208
|
+
case 'collabagenttoolcall':
|
|
209
|
+
command = [`Agent ${String(item.tool ?? 'operation')}`];
|
|
210
|
+
break;
|
|
211
|
+
case 'imagegeneration':
|
|
212
|
+
command = ['Image generation'];
|
|
213
|
+
break;
|
|
214
|
+
default:
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
const exec = {
|
|
218
|
+
callId: itemId,
|
|
219
|
+
turnId,
|
|
220
|
+
command,
|
|
221
|
+
cwd,
|
|
222
|
+
parsedCmd,
|
|
223
|
+
};
|
|
224
|
+
return {
|
|
225
|
+
kind,
|
|
226
|
+
turnId,
|
|
227
|
+
exec,
|
|
228
|
+
state: inferToolActivityState(exec),
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function normalizeCommandActions(value) {
|
|
232
|
+
if (!Array.isArray(value)) {
|
|
233
|
+
return [];
|
|
234
|
+
}
|
|
235
|
+
return value.map((entry) => {
|
|
236
|
+
const type = typeof entry?.type === 'string' ? entry.type : '';
|
|
237
|
+
if (type === 'listFiles') {
|
|
238
|
+
return { ...entry, type: 'list_files' };
|
|
239
|
+
}
|
|
240
|
+
return entry;
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
function normalizeFileChanges(value) {
|
|
244
|
+
if (!Array.isArray(value)) {
|
|
245
|
+
return [];
|
|
246
|
+
}
|
|
247
|
+
return value.map((entry) => ({
|
|
248
|
+
type: 'apply_patch',
|
|
249
|
+
path: typeof entry?.path === 'string' ? entry.path : null,
|
|
250
|
+
}));
|
|
251
|
+
}
|
|
164
252
|
export function classifyAgentOutput(phase, completed) {
|
|
165
253
|
if (!phase) {
|
|
166
254
|
return completed ? 'final_answer' : 'commentary';
|