chatccc 0.2.50 → 0.2.52
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 +51 -4
- package/config.sample.json +34 -30
- package/package.json +1 -1
- package/src/__tests__/card-plain-text.test.ts +42 -0
- package/src/__tests__/claude-adapter.test.ts +54 -1
- package/src/__tests__/config-reload.test.ts +64 -47
- package/src/__tests__/config-sample.test.ts +19 -0
- package/src/__tests__/session.test.ts +346 -1
- package/src/__tests__/stream-state.test.ts +134 -0
- package/src/__tests__/wechat-platform.test.ts +32 -0
- package/src/adapters/claude-adapter.ts +23 -2
- package/src/card-plain-text.ts +108 -0
- package/src/cards.ts +4 -4
- package/src/config.ts +775 -742
- package/src/feishu-api.ts +6 -0
- package/src/index.ts +172 -781
- package/src/orchestrator.ts +1032 -0
- package/src/platform-adapter.ts +61 -0
- package/src/session-chat-binding.ts +2 -0
- package/src/session.ts +431 -114
- package/src/sim-agent.ts +42 -31
- package/src/stream-state.ts +140 -93
- package/src/web-ui.ts +1891 -1718
- package/src/wechat-platform.ts +517 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
type JsonObject = Record<string, unknown>;
|
|
2
|
+
|
|
3
|
+
function isObject(value: unknown): value is JsonObject {
|
|
4
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function stringValue(value: unknown): string | null {
|
|
8
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function textContent(value: unknown): string | null {
|
|
12
|
+
if (typeof value === "string") return stringValue(value);
|
|
13
|
+
if (!isObject(value)) return null;
|
|
14
|
+
return stringValue(value.content);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function parseButtonValue(value: unknown): unknown {
|
|
18
|
+
if (typeof value !== "string") return value;
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse(value);
|
|
21
|
+
} catch {
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function commandFromValue(value: unknown): string | null {
|
|
27
|
+
const parsed = parseButtonValue(value);
|
|
28
|
+
if (typeof parsed === "string") {
|
|
29
|
+
const trimmed = parsed.trim();
|
|
30
|
+
return trimmed.startsWith("/") ? trimmed : null;
|
|
31
|
+
}
|
|
32
|
+
if (!isObject(parsed)) return null;
|
|
33
|
+
|
|
34
|
+
const cmd = stringValue(parsed.cmd);
|
|
35
|
+
if (cmd) return cmd.startsWith("/") ? cmd : `/${cmd}`;
|
|
36
|
+
|
|
37
|
+
const action = stringValue(parsed.action);
|
|
38
|
+
if (!action) return null;
|
|
39
|
+
|
|
40
|
+
if (action === "cd") {
|
|
41
|
+
const path = stringValue(parsed.path);
|
|
42
|
+
return path ? `/cd ${path}` : "/cd";
|
|
43
|
+
}
|
|
44
|
+
return action.startsWith("/") ? action : `/${action}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function buttonText(element: JsonObject): string | null {
|
|
48
|
+
const label = textContent(element.text);
|
|
49
|
+
const command = commandFromValue(element.value);
|
|
50
|
+
if (label && command) return `${label}: ${command}`;
|
|
51
|
+
return label ?? command;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function elementToText(element: unknown): string[] {
|
|
55
|
+
if (!isObject(element)) return [];
|
|
56
|
+
const tag = stringValue(element.tag);
|
|
57
|
+
|
|
58
|
+
if (tag === "div") {
|
|
59
|
+
const content = textContent(element.text);
|
|
60
|
+
return content ? [content] : [];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (tag === "markdown") {
|
|
64
|
+
const content = stringValue(element.content);
|
|
65
|
+
return content ? [content] : [];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (tag === "button") {
|
|
69
|
+
const content = buttonText(element);
|
|
70
|
+
return content ? [content] : [];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (tag === "action" && Array.isArray(element.actions)) {
|
|
74
|
+
return element.actions.flatMap(elementToText);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function rootElements(card: JsonObject): unknown[] {
|
|
81
|
+
if (Array.isArray(card.elements)) return card.elements;
|
|
82
|
+
if (isObject(card.body) && Array.isArray(card.body.elements)) {
|
|
83
|
+
return card.body.elements;
|
|
84
|
+
}
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function cardJsonToPlainText(cardJson: string): string | null {
|
|
89
|
+
let card: unknown;
|
|
90
|
+
try {
|
|
91
|
+
card = JSON.parse(cardJson);
|
|
92
|
+
} catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
if (!isObject(card)) return null;
|
|
96
|
+
|
|
97
|
+
const title = isObject(card.header) && isObject(card.header.title)
|
|
98
|
+
? textContent(card.header.title)
|
|
99
|
+
: null;
|
|
100
|
+
const lines = rootElements(card).flatMap(elementToText);
|
|
101
|
+
const parts = title ? [`# ${title}`, ...lines] : lines;
|
|
102
|
+
const text = parts
|
|
103
|
+
.map((part) => part.trim())
|
|
104
|
+
.filter(Boolean)
|
|
105
|
+
.join("\n\n")
|
|
106
|
+
.trim();
|
|
107
|
+
return text || null;
|
|
108
|
+
}
|
package/src/cards.ts
CHANGED
|
@@ -115,11 +115,11 @@ export function buildHelpCard(
|
|
|
115
115
|
const greeting = opts.greeting ?? `你发送了: ${userText}`;
|
|
116
116
|
const defaultToolLabel = opts.defaultToolLabel ?? "Claude Code";
|
|
117
117
|
const lines = [
|
|
118
|
-
`发送 **/new**
|
|
119
|
-
"发送 **/new claude** 创建新 Claude
|
|
118
|
+
`发送 **/new** 创建新会话(使用 /cd 设置的目录,默认 ${defaultToolLabel})`,
|
|
119
|
+
"发送 **/new claude** 创建新 Claude 会话",
|
|
120
120
|
"发送 **/new cursor** 创建新 Cursor 会话",
|
|
121
121
|
"发送 **/new codex** 创建新 Codex 会话",
|
|
122
|
-
"发送 **/newh**
|
|
122
|
+
"发送 **/newh** 重置当前会话(沿用当前工作目录,不切换)",
|
|
123
123
|
].join("\n");
|
|
124
124
|
return JSON.stringify({
|
|
125
125
|
config: { wide_screen_mode: true },
|
|
@@ -212,7 +212,7 @@ export function buildCdCard(
|
|
|
212
212
|
elements.push({ tag: "hr" });
|
|
213
213
|
elements.push({
|
|
214
214
|
tag: "div",
|
|
215
|
-
text: { tag: "lark_md", content: "
|
|
215
|
+
text: { tag: "lark_md", content: "**最近使用过的路径:**" },
|
|
216
216
|
});
|
|
217
217
|
elements.push({
|
|
218
218
|
tag: "action",
|