chatccc 0.2.66 → 0.2.67
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/im-skills/wechat-image-skill/skill.md +10 -10
- package/package.json +1 -1
- package/src/im-skills.ts +31 -0
- package/src/orchestrator.ts +4 -3
- package/src/session.ts +2 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: wechat-image-skill
|
|
3
|
-
description: WeChat iLink local skills for sending and receiving images.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
Current working directory: {{cwd}}
|
|
7
|
-
|
|
8
|
-
WeChat images are handled through the iLink SDK. The local server does NOT have HTTP RPC endpoints for WeChat; use the helper scripts below instead.
|
|
9
|
-
|
|
10
|
-
- **Receive images**: Images sent to the bot are automatically downloaded to `~/.chatccc/images/downloads/` with the filename prefix `wx_`. The message text will include the local path as `[图片] <absolute path>` — read `{{im_skills_cache_dir}}/wechat-image-skill/receive-send-image.md`
|
|
1
|
+
---
|
|
2
|
+
name: wechat-image-skill
|
|
3
|
+
description: WeChat iLink local skills for sending and receiving images.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Current working directory: {{cwd}}
|
|
7
|
+
|
|
8
|
+
WeChat images are handled through the iLink SDK. The local server does NOT have HTTP RPC endpoints for WeChat; use the helper scripts below instead.
|
|
9
|
+
|
|
10
|
+
- **Receive images**: Images sent to the bot are automatically downloaded to `~/.chatccc/images/downloads/` with the filename prefix `wx_`. The message text will include the local path as `[图片] <absolute path>` — read `{{im_skills_cache_dir}}/wechat-image-skill/receive-send-image.md`
|
|
11
11
|
- **Send images**: Use the send-image helper script — read `{{im_skills_cache_dir}}/wechat-image-skill/receive-send-image.md`
|
package/package.json
CHANGED
package/src/im-skills.ts
CHANGED
|
@@ -70,6 +70,37 @@ export async function buildImSkillsPrompt(input: BuildImSkillsPromptInput): Prom
|
|
|
70
70
|
.join("\n\n");
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// 会话级缓存:相同 session_id + cwd 的渲染结果完全相同,避免每轮重复读文件+渲染
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
const promptCache = new Map<string, string>();
|
|
78
|
+
|
|
79
|
+
function promptCacheKey(input: BuildImSkillsPromptInput): string {
|
|
80
|
+
const names = input.enabledSkillNames
|
|
81
|
+
? [...input.enabledSkillNames].sort().join(",")
|
|
82
|
+
: "*";
|
|
83
|
+
const { session_id, cwd } = input.variables;
|
|
84
|
+
return `${input.skillsDir ?? DEFAULT_IM_SKILLS_DIR}|${names}|${session_id}|${cwd}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** 带会话级缓存的 buildImSkillsPrompt。同 session + 同 cwd 时直接返回缓存的渲染结果。 */
|
|
88
|
+
export async function buildImSkillsPromptCached(input: BuildImSkillsPromptInput): Promise<string> {
|
|
89
|
+
const key = promptCacheKey(input);
|
|
90
|
+
const cached = promptCache.get(key);
|
|
91
|
+
if (cached !== undefined) return cached;
|
|
92
|
+
const result = await buildImSkillsPrompt(input);
|
|
93
|
+
promptCache.set(key, result);
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** 清除指定会话的缓存(如 /cd 后 cwd 变了,旧 key 不再需要) */
|
|
98
|
+
export function clearImSkillsPromptCache(sessionId: string): void {
|
|
99
|
+
for (const key of promptCache.keys()) {
|
|
100
|
+
if (key.includes(`|${sessionId}|`)) promptCache.delete(key);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
73
104
|
/**
|
|
74
105
|
* 渲染技能目录下的子文档(skill.md 除外)并写入 outputDir。
|
|
75
106
|
* 返回写入的文件路径列表。通常在会话初始化时调用,写入的文档供 Agent 按需读取。
|
package/src/orchestrator.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
setDefaultCwd,
|
|
22
22
|
getRecentDirs,
|
|
23
23
|
addRecentDir,
|
|
24
|
+
resolveDefaultAgentTool,
|
|
24
25
|
sessionPrefixForTool,
|
|
25
26
|
toolDisplayName,
|
|
26
27
|
ts,
|
|
@@ -240,7 +241,7 @@ export async function handleCommand(
|
|
|
240
241
|
|
|
241
242
|
if (textLower === "/new" || textLower.startsWith("/new ")) {
|
|
242
243
|
const toolArg = text.slice(5).trim().toLowerCase();
|
|
243
|
-
const tool = toolArg ||
|
|
244
|
+
const tool = toolArg || resolveDefaultAgentTool();
|
|
244
245
|
logTrace(tid, "BRANCH", { cmd: "/new", tool });
|
|
245
246
|
const validTools = ["claude", "cursor", "codex"];
|
|
246
247
|
if (!validTools.includes(tool)) {
|
|
@@ -643,7 +644,7 @@ export async function handleCommand(
|
|
|
643
644
|
model: s.model,
|
|
644
645
|
tool: s.tool,
|
|
645
646
|
}));
|
|
646
|
-
const card = buildSessionsCard(cardData);
|
|
647
|
+
const card = buildSessionsCard(cardData, { defaultToolLabel: toolDisplayName(resolveDefaultAgentTool()) });
|
|
647
648
|
const ok = await platform.sendRawCard(chatId, card);
|
|
648
649
|
console.log(
|
|
649
650
|
`[${ts()}] [SESSIONS] card sent, ok=${ok}, count=${cardData.length}`,
|
|
@@ -1032,7 +1033,7 @@ export async function handleCommand(
|
|
|
1032
1033
|
|
|
1033
1034
|
// 无会话上下文 → help card
|
|
1034
1035
|
logTrace(tid, "SEND", { method: "help_card", chatId });
|
|
1035
|
-
const card = buildHelpCard(text);
|
|
1036
|
+
const card = buildHelpCard(text, { defaultToolLabel: toolDisplayName(resolveDefaultAgentTool()) });
|
|
1036
1037
|
const ok = await platform.sendRawCard(chatId, card);
|
|
1037
1038
|
if (!ok) {
|
|
1038
1039
|
console.error(`[${ts()}] [SEND] help_card FAIL: chatId=${chatId}`);
|
package/src/session.ts
CHANGED
|
@@ -28,7 +28,7 @@ import type { ToolAdapter } from "./adapters/adapter-interface.ts";
|
|
|
28
28
|
import { createClaudeAdapter } from "./adapters/claude-adapter.ts";
|
|
29
29
|
import { createCursorAdapter } from "./adapters/cursor-adapter.ts";
|
|
30
30
|
import { createCodexAdapter } from "./adapters/codex-adapter.ts";
|
|
31
|
-
import {
|
|
31
|
+
import { buildImSkillsPromptCached, exportSkillSubDocs, clearImSkillsPromptCache } from "./im-skills.ts";
|
|
32
32
|
import type { PlatformAdapter } from "./platform-adapter.ts";
|
|
33
33
|
|
|
34
34
|
// 微信显示循环压缩:头5 + ... + 尾5,避免在最后一步 sendText 中压缩指令回复
|
|
@@ -734,7 +734,7 @@ export async function runAgentSession(
|
|
|
734
734
|
wechat_send_video_script: join(wechatVideoSkillDir, "send-video.mjs"),
|
|
735
735
|
};
|
|
736
736
|
const enabledSkillNames = imSkillNamesForPlatform(platform);
|
|
737
|
-
var imSkillsPrompt = await
|
|
737
|
+
var imSkillsPrompt = await buildImSkillsPromptCached({ variables: skillVariables, enabledSkillNames });
|
|
738
738
|
await exportSkillSubDocs({ variables: skillVariables, enabledSkillNames }, imSkillsCacheDir);
|
|
739
739
|
var userTextWithCapabilities = [
|
|
740
740
|
...(imSkillsPrompt ? [imSkillsPrompt, ""] : []),
|