pikiclaw 0.3.50 → 0.3.51
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 +1 -3
- package/README.zh-CN.md +1 -3
- package/dist/bot/streaming.js +61 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ npx pikiclaw@latest
|
|
|
24
24
|
<b>English</b> | <a href="README.zh-CN.md">简体中文</a>
|
|
25
25
|
</p>
|
|
26
26
|
|
|
27
|
-
<img src="docs/workspace.png" alt="Workspace" width="780">
|
|
27
|
+
<img src="docs/promo-dashboard-workspace.png" alt="Workspace" width="780">
|
|
28
28
|
|
|
29
29
|
</div>
|
|
30
30
|
|
|
@@ -313,8 +313,6 @@ The shape that truly matters: **You never have to leave your preferred environme
|
|
|
313
313
|
- **Richer Tool Ecosystem** — Releasing official MCP packs, skill templates, and a community marketplace.
|
|
314
314
|
- **Cross-Platform Computer-Use** — Extending desktop control drivers beyond macOS to support Windows and Linux.
|
|
315
315
|
|
|
316
|
-
For protocol-level insights, see our [ACP Migration Plan](docs/acp-migration.md).
|
|
317
|
-
|
|
318
316
|
---
|
|
319
317
|
|
|
320
318
|
## Development
|
package/README.zh-CN.md
CHANGED
|
@@ -24,7 +24,7 @@ npx pikiclaw@latest
|
|
|
24
24
|
<a href="README.md">English</a> | <b>简体中文</b>
|
|
25
25
|
</p>
|
|
26
26
|
|
|
27
|
-
<img src="docs/workspace.png" alt="工作区" width="780">
|
|
27
|
+
<img src="docs/promo-dashboard-workspace.png" alt="工作区" width="780">
|
|
28
28
|
|
|
29
29
|
</div>
|
|
30
30
|
|
|
@@ -312,8 +312,6 @@ docker run -d --name pikiclaw -p 3939:3939 \
|
|
|
312
312
|
- **完善工具生态** —— 推出官方推荐的 MCP 插件合集、Skill 模版库及社区应用市场。
|
|
313
313
|
- **全平台的 Computer-use** —— 在已有的 macOS Peekaboo 驱动之外,加入适配 Windows / Linux 操作系统的桌面控制支持。
|
|
314
314
|
|
|
315
|
-
想了解协议层的下一步动作,请参阅 [ACP 迁移计划](docs/acp-migration.md)。
|
|
316
|
-
|
|
317
315
|
---
|
|
318
316
|
|
|
319
317
|
## 本地开发
|
package/dist/bot/streaming.js
CHANGED
|
@@ -8,16 +8,19 @@
|
|
|
8
8
|
* the dashboard ultimately shows, do it in the dashboard layer instead.
|
|
9
9
|
*/
|
|
10
10
|
/**
|
|
11
|
-
* Shrink absolute paths that bloat IM cards on small screens.
|
|
12
|
-
*
|
|
13
|
-
* while the leading `/Users/…/long/project/root/` noise is
|
|
14
|
-
*
|
|
11
|
+
* Shrink absolute paths that bloat IM cards on small screens. Any absolute
|
|
12
|
+
* path with 4+ segments collapses to `…/<last-two-segments>` so directory
|
|
13
|
+
* context is kept while the leading `/Users/…/long/project/root/` noise is
|
|
14
|
+
* dropped. Length-based gating made the output inconsistent — borderline
|
|
15
|
+
* paths (47 chars) sat next to compacted ones (52 chars), making the activity
|
|
16
|
+
* list look broken. Relative paths and short paths (<4 segments, e.g.
|
|
17
|
+
* `~/foo`, `/tmp/x.log`) are passed through unchanged.
|
|
15
18
|
*/
|
|
16
19
|
function compactActivityPath(token) {
|
|
17
|
-
if (
|
|
20
|
+
if (!token.includes('/'))
|
|
18
21
|
return token;
|
|
19
22
|
const segments = token.split('/').filter(Boolean);
|
|
20
|
-
if (segments.length <
|
|
23
|
+
if (segments.length < 4)
|
|
21
24
|
return token;
|
|
22
25
|
const tail = segments.slice(-2).join('/');
|
|
23
26
|
return `…/${tail}`;
|
|
@@ -33,6 +36,12 @@ function compactPathsInActivityLine(line) {
|
|
|
33
36
|
});
|
|
34
37
|
}
|
|
35
38
|
const TOOL_DONE_RE = /^(.+?)\s+(done|failed)$/;
|
|
39
|
+
/** "X -> Y" pattern produced by `summarizeClaudeToolResult` for tools whose
|
|
40
|
+
* result has body text (im_ask_user, ToolSearch, MCP tools, …). The Y half
|
|
41
|
+
* is the tool's response — capturing it lets us collapse the pre-event
|
|
42
|
+
* (`Ask user: q`) and the post-event (`Ask user: q -> A: …`) into a single
|
|
43
|
+
* line in the narrative instead of leaving both sitting around. */
|
|
44
|
+
const TOOL_ARROW_RE = /^(.+?)\s*->\s*(.+)$/;
|
|
36
45
|
const INJECTED_PROMPT_MARKERS = [
|
|
37
46
|
'\n[Session Workspace]',
|
|
38
47
|
'\n[Telegram Artifact Return]',
|
|
@@ -172,13 +181,58 @@ export function parseActivitySummary(activity) {
|
|
|
172
181
|
narrative.push(status === 'failed' ? `${baseKey} failed` : baseKey);
|
|
173
182
|
continue;
|
|
174
183
|
}
|
|
184
|
+
// Pair "X" → "X -> Y" (im_ask_user, ToolSearch, MCP tools, … — any tool
|
|
185
|
+
// whose summarizeClaudeToolResult fell into the arrow branch). Without
|
|
186
|
+
// this, the IM card shows the question and the answered form side by
|
|
187
|
+
// side. We replace the pending entry with the full arrow form so the
|
|
188
|
+
// narrative carries the answer in a single line.
|
|
189
|
+
const arrowMatch = line.match(TOOL_ARROW_RE);
|
|
190
|
+
if (arrowMatch) {
|
|
191
|
+
const baseKey = arrowMatch[1].trim();
|
|
192
|
+
const idx = popPending(baseKey);
|
|
193
|
+
if (idx != null) {
|
|
194
|
+
narrative[idx] = line;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
175
198
|
pushPending(line, narrative.length);
|
|
176
199
|
narrative.push(line);
|
|
177
200
|
}
|
|
178
201
|
for (const pending of activeClaudeShells.values()) {
|
|
179
202
|
activeCommands += pending;
|
|
180
203
|
}
|
|
181
|
-
return { narrative, failedCommands, completedCommands, activeCommands };
|
|
204
|
+
return { narrative: collapseConsecutiveDuplicates(narrative), failedCommands, completedCommands, activeCommands };
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Walk the narrative and collapse runs of identical lines into `X ×N`. The
|
|
208
|
+
* input narrative often contains repeats when the model calls the same tool
|
|
209
|
+
* multiple times in a row (two consecutive `Edit README.md`, three `Read X`,
|
|
210
|
+
* …) — listing them N times wastes IM card real estate without adding
|
|
211
|
+
* information. Non-adjacent duplicates are preserved to keep the temporal
|
|
212
|
+
* order intact.
|
|
213
|
+
*/
|
|
214
|
+
function collapseConsecutiveDuplicates(narrative) {
|
|
215
|
+
const out = [];
|
|
216
|
+
let runStart = -1;
|
|
217
|
+
let runCount = 0;
|
|
218
|
+
const flush = () => {
|
|
219
|
+
if (runStart < 0)
|
|
220
|
+
return;
|
|
221
|
+
out.push(runCount > 1 ? `${narrative[runStart]} ×${runCount}` : narrative[runStart]);
|
|
222
|
+
runStart = -1;
|
|
223
|
+
runCount = 0;
|
|
224
|
+
};
|
|
225
|
+
for (let i = 0; i < narrative.length; i++) {
|
|
226
|
+
if (runStart >= 0 && narrative[i] === narrative[runStart]) {
|
|
227
|
+
runCount++;
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
flush();
|
|
231
|
+
runStart = i;
|
|
232
|
+
runCount = 1;
|
|
233
|
+
}
|
|
234
|
+
flush();
|
|
235
|
+
return out;
|
|
182
236
|
}
|
|
183
237
|
export function formatActivityCommandSummary(completedCommands, activeCommands, failedCommands = 0) {
|
|
184
238
|
const parts = [];
|
package/package.json
CHANGED