@cc-soul/openclaw 1.0.0
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 +284 -0
- package/cc-soul/HOOK.md +18 -0
- package/cc-soul/body.js +129 -0
- package/cc-soul/cli.js +263 -0
- package/cc-soul/cognition.js +143 -0
- package/cc-soul/context-prep.js +1 -0
- package/cc-soul/epistemic.js +1 -0
- package/cc-soul/evolution.js +176 -0
- package/cc-soul/features.js +79 -0
- package/cc-soul/federation.js +207 -0
- package/cc-soul/fingerprint.js +1 -0
- package/cc-soul/flow.js +199 -0
- package/cc-soul/graph.js +85 -0
- package/cc-soul/handler.js +609 -0
- package/cc-soul/inner-life.js +1 -0
- package/cc-soul/lorebook.js +94 -0
- package/cc-soul/memory.js +688 -0
- package/cc-soul/metacognition.js +1 -0
- package/cc-soul/notify.js +88 -0
- package/cc-soul/patterns.js +1 -0
- package/cc-soul/persistence.js +147 -0
- package/cc-soul/persona.js +1 -0
- package/cc-soul/prompt-builder.js +322 -0
- package/cc-soul/quality.js +135 -0
- package/cc-soul/rover.js +1 -0
- package/cc-soul/sync.js +274 -0
- package/cc-soul/tasks.js +1 -0
- package/cc-soul/types.js +0 -0
- package/cc-soul/upgrade.js +1 -0
- package/cc-soul/user-profiles.js +1 -0
- package/cc-soul/values.js +1 -0
- package/cc-soul/voice.js +1 -0
- package/hub/dashboard.html +236 -0
- package/hub/package.json +16 -0
- package/hub/server.ts +447 -0
- package/package.json +29 -0
- package/scripts/cli.js +136 -0
- package/scripts/install.js +106 -0
package/cc-soul/cli.js
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { spawn } from "child_process";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
import { existsSync, readFileSync } from "fs";
|
|
6
|
+
import { DATA_DIR, loadJson } from "./persistence.ts";
|
|
7
|
+
import { resolve } from "path";
|
|
8
|
+
const OPENCLAW_CONFIG_PATH = resolve(homedir(), ".openclaw/openclaw.json");
|
|
9
|
+
const AI_CONFIG_PATH = resolve(DATA_DIR, "ai_config.json");
|
|
10
|
+
function detectAIConfig() {
|
|
11
|
+
const userConfig = loadJson(AI_CONFIG_PATH, {});
|
|
12
|
+
if (userConfig.backend) {
|
|
13
|
+
console.log(`[cc-soul][ai] using user override from ai_config.json`);
|
|
14
|
+
return {
|
|
15
|
+
backend: userConfig.backend,
|
|
16
|
+
cli_command: userConfig.cli_command || "claude",
|
|
17
|
+
cli_args: userConfig.cli_args || ["-p"],
|
|
18
|
+
api_base: userConfig.api_base || "https://api.openai.com/v1",
|
|
19
|
+
api_key: userConfig.api_key || "",
|
|
20
|
+
api_model: userConfig.api_model || "gpt-4o",
|
|
21
|
+
max_concurrent: userConfig.max_concurrent || 5
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
if (existsSync(OPENCLAW_CONFIG_PATH)) {
|
|
26
|
+
const raw = JSON.parse(readFileSync(OPENCLAW_CONFIG_PATH, "utf-8"));
|
|
27
|
+
const agents = raw?.agents?.defaults || {};
|
|
28
|
+
const modelRef = agents?.model?.primary || "";
|
|
29
|
+
const cliBackends = agents?.cliBackends || {};
|
|
30
|
+
if (modelRef) {
|
|
31
|
+
const [provider] = modelRef.split("/");
|
|
32
|
+
const backendDef = cliBackends[provider];
|
|
33
|
+
if (backendDef?.command) {
|
|
34
|
+
const command = backendDef.command;
|
|
35
|
+
const args = backendDef.args || (command === "claude" ? ["-p"] : []);
|
|
36
|
+
console.log(`[cc-soul][ai] auto-detected from openclaw.json: CLI "${command}" (${modelRef})`);
|
|
37
|
+
return {
|
|
38
|
+
backend: "cli",
|
|
39
|
+
cli_command: command,
|
|
40
|
+
cli_args: command === "claude" ? ["-p"] : args,
|
|
41
|
+
api_base: "",
|
|
42
|
+
api_key: "",
|
|
43
|
+
api_model: "",
|
|
44
|
+
max_concurrent: 5
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const env = raw?.env || {};
|
|
49
|
+
const openaiKey = env.OPENAI_API_KEY || "";
|
|
50
|
+
const anthropicKey = env.ANTHROPIC_API_KEY || "";
|
|
51
|
+
if (openaiKey) {
|
|
52
|
+
console.log(`[cc-soul][ai] auto-detected from openclaw.json: OpenAI API`);
|
|
53
|
+
return {
|
|
54
|
+
backend: "openai-compatible",
|
|
55
|
+
cli_command: "",
|
|
56
|
+
cli_args: [],
|
|
57
|
+
api_base: "https://api.openai.com/v1",
|
|
58
|
+
api_key: openaiKey,
|
|
59
|
+
api_model: "gpt-4o-mini",
|
|
60
|
+
// use cheap model for soul operations
|
|
61
|
+
max_concurrent: 8
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
} catch (e) {
|
|
66
|
+
console.error(`[cc-soul][ai] failed to read openclaw.json: ${e.message}`);
|
|
67
|
+
}
|
|
68
|
+
console.log(`[cc-soul][ai] using default: claude CLI`);
|
|
69
|
+
return {
|
|
70
|
+
backend: "cli",
|
|
71
|
+
cli_command: "claude",
|
|
72
|
+
cli_args: ["-p"],
|
|
73
|
+
api_base: "",
|
|
74
|
+
api_key: "",
|
|
75
|
+
api_model: "",
|
|
76
|
+
max_concurrent: 5
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
__name(detectAIConfig, "detectAIConfig");
|
|
80
|
+
let aiConfig = detectAIConfig();
|
|
81
|
+
function loadAIConfig() {
|
|
82
|
+
aiConfig = detectAIConfig();
|
|
83
|
+
}
|
|
84
|
+
__name(loadAIConfig, "loadAIConfig");
|
|
85
|
+
function getAIConfig() {
|
|
86
|
+
return aiConfig;
|
|
87
|
+
}
|
|
88
|
+
__name(getAIConfig, "getAIConfig");
|
|
89
|
+
let activeCLICount = 0;
|
|
90
|
+
function spawnCLI(prompt, callback, timeoutMs = 3e4) {
|
|
91
|
+
if (activeCLICount >= aiConfig.max_concurrent) {
|
|
92
|
+
console.log(`[cc-soul][ai] throttled (${activeCLICount}/${aiConfig.max_concurrent} active), skipping`);
|
|
93
|
+
callback("");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (aiConfig.backend === "openai-compatible") {
|
|
97
|
+
callOpenAICompatible(prompt, callback, timeoutMs);
|
|
98
|
+
} else {
|
|
99
|
+
callCLI(prompt, callback, timeoutMs);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
__name(spawnCLI, "spawnCLI");
|
|
103
|
+
function callCLI(prompt, callback, timeoutMs) {
|
|
104
|
+
activeCLICount++;
|
|
105
|
+
let settled = false;
|
|
106
|
+
function release() {
|
|
107
|
+
if (!settled) {
|
|
108
|
+
settled = true;
|
|
109
|
+
activeCLICount--;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
__name(release, "release");
|
|
113
|
+
try {
|
|
114
|
+
const args = [...aiConfig.cli_args, prompt, "--no-input"];
|
|
115
|
+
const proc = spawn(aiConfig.cli_command, args, {
|
|
116
|
+
cwd: homedir(),
|
|
117
|
+
timeout: timeoutMs,
|
|
118
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
119
|
+
});
|
|
120
|
+
const MAX_OUTPUT = 512 * 1024;
|
|
121
|
+
let output = "";
|
|
122
|
+
proc.stdout?.on("data", (d) => {
|
|
123
|
+
if (output.length < MAX_OUTPUT) {
|
|
124
|
+
output += d.toString();
|
|
125
|
+
if (output.length > MAX_OUTPUT) {
|
|
126
|
+
output = output.slice(0, MAX_OUTPUT);
|
|
127
|
+
console.log(`[cc-soul][ai] output truncated at ${MAX_OUTPUT / 1024}KB`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
proc.stderr?.on("data", () => {
|
|
132
|
+
});
|
|
133
|
+
const heartbeat = setInterval(() => {
|
|
134
|
+
console.log(`[cc-soul][ai] processing... (${Math.round(output.length / 1024)}kb received)`);
|
|
135
|
+
}, 6e4);
|
|
136
|
+
proc.on("close", (code, signal) => {
|
|
137
|
+
clearInterval(heartbeat);
|
|
138
|
+
release();
|
|
139
|
+
if (signal === "SIGTERM") {
|
|
140
|
+
console.log(`[cc-soul][ai] CLI timeout after ${timeoutMs}ms`);
|
|
141
|
+
callback("");
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
callback(output.trim() || "");
|
|
145
|
+
});
|
|
146
|
+
proc.on("error", (err) => {
|
|
147
|
+
clearInterval(heartbeat);
|
|
148
|
+
release();
|
|
149
|
+
console.error(`[cc-soul][ai] CLI error: ${err.message}`);
|
|
150
|
+
callback("");
|
|
151
|
+
});
|
|
152
|
+
} catch (err) {
|
|
153
|
+
release();
|
|
154
|
+
console.error(`[cc-soul][ai] CLI spawn failed: ${err.message}`);
|
|
155
|
+
callback("");
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
__name(callCLI, "callCLI");
|
|
159
|
+
async function callOpenAICompatible(prompt, callback, timeoutMs) {
|
|
160
|
+
activeCLICount++;
|
|
161
|
+
const controller = new AbortController();
|
|
162
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
163
|
+
try {
|
|
164
|
+
const resp = await fetch(`${aiConfig.api_base}/chat/completions`, {
|
|
165
|
+
method: "POST",
|
|
166
|
+
headers: {
|
|
167
|
+
"Content-Type": "application/json",
|
|
168
|
+
"Authorization": `Bearer ${aiConfig.api_key}`
|
|
169
|
+
},
|
|
170
|
+
body: JSON.stringify({
|
|
171
|
+
model: aiConfig.api_model,
|
|
172
|
+
messages: [{ role: "user", content: prompt }],
|
|
173
|
+
max_tokens: 2048,
|
|
174
|
+
temperature: 0.7
|
|
175
|
+
}),
|
|
176
|
+
signal: controller.signal
|
|
177
|
+
});
|
|
178
|
+
clearTimeout(timer);
|
|
179
|
+
if (!resp.ok) {
|
|
180
|
+
const errText = await resp.text().catch(() => "");
|
|
181
|
+
console.error(`[cc-soul][ai] API error ${resp.status}: ${errText.slice(0, 200)}`);
|
|
182
|
+
callback("");
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const data = await resp.json();
|
|
186
|
+
const content = data.choices?.[0]?.message?.content || "";
|
|
187
|
+
callback(content.trim());
|
|
188
|
+
} catch (e) {
|
|
189
|
+
clearTimeout(timer);
|
|
190
|
+
if (e.name === "AbortError") {
|
|
191
|
+
console.log(`[cc-soul][ai] API timeout after ${timeoutMs}ms`);
|
|
192
|
+
} else {
|
|
193
|
+
console.error(`[cc-soul][ai] API error: ${e.message}`);
|
|
194
|
+
}
|
|
195
|
+
callback("");
|
|
196
|
+
} finally {
|
|
197
|
+
activeCLICount--;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
__name(callOpenAICompatible, "callOpenAICompatible");
|
|
201
|
+
const EMPTY_RESULT = {
|
|
202
|
+
memories: [],
|
|
203
|
+
entities: [],
|
|
204
|
+
satisfaction: "NEUTRAL",
|
|
205
|
+
quality: { score: 5, issues: [] },
|
|
206
|
+
emotion: "neutral",
|
|
207
|
+
reflection: null,
|
|
208
|
+
curiosity: null
|
|
209
|
+
};
|
|
210
|
+
function runPostResponseAnalysis(userMsg, botResponse, callback) {
|
|
211
|
+
const prompt = `\u5206\u6790\u4EE5\u4E0B\u5BF9\u8BDD\uFF0C\u4E25\u683C\u6309JSON\u8F93\u51FA\uFF08\u4E0D\u8981\u5176\u4ED6\u6587\u5B57\uFF09\uFF1A
|
|
212
|
+
|
|
213
|
+
\u7528\u6237: "${userMsg.slice(0, 500)}"
|
|
214
|
+
\u56DE\u590D: "${botResponse.slice(0, 500)}"
|
|
215
|
+
|
|
216
|
+
\u8BF7\u540C\u65F6\u5B8C\u6210\u4EE5\u4E0B\u5206\u6790\uFF1A
|
|
217
|
+
1. memories: \u63D0\u53D6\u503C\u5F97\u957F\u671F\u8BB0\u4F4F\u7684\u4FE1\u606F\u3002\u6BCF\u6761: {"content":"\u5185\u5BB9","scope":"\u7C7B\u578B","visibility":"\u53EF\u89C1\u6027"}\uFF0Cscope\u53EA\u80FD\u662F: preference/fact/event/opinion\u3002visibility\u53EA\u80FD\u662F: global(\u901A\u7528\u77E5\u8BC6/\u6280\u672F\u4E8B\u5B9E\uFF0C\u5BF9\u6240\u6709\u4EBA\u6709\u7528)/channel(\u9891\u9053\u76F8\u5173\uFF0C\u53EA\u5728\u5F53\u524D\u7FA4\u6709\u7528)/private(\u4E2A\u4EBA\u76F8\u5173\uFF0C\u53EA\u5BF9\u5F53\u524D\u7528\u6237\u6709\u7528)\u3002\u6CA1\u6709\u5C31\u7A7A\u6570\u7EC4\u3002
|
|
218
|
+
2. entities: \u63D0\u53D6\u4EBA\u540D\u3001\u9879\u76EE\u540D\u3001\u516C\u53F8\u540D\u3001\u6280\u672F\u540D\u3002\u6BCF\u6761: {"name":"\u540D","type":"\u7C7B\u578B","relation":"\u5173\u7CFB"}\uFF0Ctype\u53EA\u80FD\u662F: person/project/company/tech/place\u3002\u6CA1\u6709\u5C31\u7A7A\u6570\u7EC4\u3002
|
|
219
|
+
3. satisfaction: \u5224\u65AD\u7528\u6237\u5BF9\u56DE\u590D\u7684\u6EE1\u610F\u5EA6: POSITIVE/NEUTRAL/NEGATIVE/TOO_VERBOSE
|
|
220
|
+
4. quality: \u56DE\u590D\u8D28\u91CF\u8BC4\u52061-10 + \u95EE\u9898\u5217\u8868\u3002{"score":N,"issues":["\u95EE\u9898"]}
|
|
221
|
+
5. emotion: \u5BF9\u8BDD\u60C5\u611F\u6807\u7B7E: neutral/warm/important/painful/funny
|
|
222
|
+
6. reflection: \u56DE\u590D\u6709\u4EC0\u4E48\u9057\u61BE\u6216\u53EF\u6539\u8FDB\u7684\uFF1F1\u53E5\u8BDD\uFF0C\u6CA1\u6709\u5C31null
|
|
223
|
+
7. curiosity: \u4F5C\u4E3A\u670B\u53CB\u60F3\u8FFD\u95EE\u4EC0\u4E48\uFF1F1\u53E5\u8BDD\uFF0C\u6CA1\u6709\u5C31null
|
|
224
|
+
|
|
225
|
+
JSON\u683C\u5F0F(\u4E25\u683C):
|
|
226
|
+
{"memories":[],"entities":[],"satisfaction":"NEUTRAL","quality":{"score":5,"issues":[]},"emotion":"neutral","reflection":null,"curiosity":null}`;
|
|
227
|
+
spawnCLI(
|
|
228
|
+
prompt,
|
|
229
|
+
(output) => {
|
|
230
|
+
try {
|
|
231
|
+
const match = output.match(/\{[\s\S]*\}/);
|
|
232
|
+
if (match) {
|
|
233
|
+
const result = JSON.parse(match[0]);
|
|
234
|
+
callback({
|
|
235
|
+
memories: (result.memories || []).map((m) => ({
|
|
236
|
+
content: m.content,
|
|
237
|
+
scope: m.scope,
|
|
238
|
+
visibility: m.visibility || void 0
|
|
239
|
+
})),
|
|
240
|
+
entities: result.entities || [],
|
|
241
|
+
satisfaction: result.satisfaction || "NEUTRAL",
|
|
242
|
+
quality: result.quality || { score: 5, issues: [] },
|
|
243
|
+
emotion: result.emotion || "neutral",
|
|
244
|
+
reflection: result.reflection || null,
|
|
245
|
+
curiosity: result.curiosity || null
|
|
246
|
+
});
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
} catch (e) {
|
|
250
|
+
console.error(`[cc-soul][ai] analysis parse error: ${e.message}`);
|
|
251
|
+
}
|
|
252
|
+
callback({ ...EMPTY_RESULT });
|
|
253
|
+
},
|
|
254
|
+
45e3
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
__name(runPostResponseAnalysis, "runPostResponseAnalysis");
|
|
258
|
+
export {
|
|
259
|
+
getAIConfig,
|
|
260
|
+
loadAIConfig,
|
|
261
|
+
runPostResponseAnalysis,
|
|
262
|
+
spawnCLI
|
|
263
|
+
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { body, bodyOnCorrection, bodyOnPositiveFeedback } from "./body.ts";
|
|
4
|
+
import { getProfile, getProfileTier } from "./user-profiles.ts";
|
|
5
|
+
function attentionGate(msg) {
|
|
6
|
+
const m = msg.toLowerCase();
|
|
7
|
+
const correctionWords = ["\u4E0D\u5BF9", "\u9519\u4E86", "\u641E\u9519", "\u7406\u89E3\u9519", "\u4E0D\u662F\u8FD9\u6837", "\u8BF4\u53CD\u4E86", "\u522B\u778E\u8BF4", "wrong", "\u91CD\u6765"];
|
|
8
|
+
const notCorrection = ["\u6CA1\u9519", "\u4E0D\u9519", "\u5BF9\u4E0D\u5BF9", "\u9519\u4E86\u5417", "\u662F\u4E0D\u662F\u9519", "\u4E0D\u5BF9\u79F0", "\u4E0D\u5BF9\u52B2", "\u9519\u4E86\u9519\u4E86\u6211\u7684", "\u4F60\u8BF4\u5F97\u5BF9", "\u6CA1\u6709\u9519"];
|
|
9
|
+
if (correctionWords.some((w) => m.includes(w))) {
|
|
10
|
+
if (!notCorrection.some((w) => m.includes(w))) {
|
|
11
|
+
return { type: "correction", priority: 10 };
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
if (["\u70E6", "\u7D2F", "\u96BE\u8FC7", "\u5D29\u6E83", "\u538B\u529B\u5927", "\u7126\u8651", "\u5F00\u5FC3", "\u54C8\u54C8", "\u725B\u903C", "\u592A\u68D2", "\u611F\u8C22", "\u8C22\u8C22"].some((w) => m.includes(w))) {
|
|
15
|
+
return { type: "emotional", priority: 7 };
|
|
16
|
+
}
|
|
17
|
+
if (["\u4EE3\u7801", "\u51FD\u6570", "\u62A5\u9519", "error", "bug", "crash", "\u7F16\u8BD1", "\u8C03\u8BD5", "debug", "\u5B9E\u73B0", "\u600E\u4E48\u5199", "hook", "frida", "ida"].some((w) => m.includes(w))) {
|
|
18
|
+
return { type: "technical", priority: 8 };
|
|
19
|
+
}
|
|
20
|
+
if (msg.length < 15 || ["\u55EF", "\u597D", "\u54E6", "\u884C", "\u53EF\u4EE5", "ok", "\u660E\u767D"].some((w) => m === w || m === w + "\u7684")) {
|
|
21
|
+
return { type: "casual", priority: 3 };
|
|
22
|
+
}
|
|
23
|
+
return { type: "general", priority: 5 };
|
|
24
|
+
}
|
|
25
|
+
__name(attentionGate, "attentionGate");
|
|
26
|
+
function detectIntent(msg) {
|
|
27
|
+
const m = msg.toLowerCase();
|
|
28
|
+
if (["\u4F60\u89C9\u5F97", "\u4F60\u770B", "\u4F60\u8BA4\u4E3A", "\u4F60\u600E\u4E48\u770B", "\u4F60\u7684\u770B\u6CD5", "\u5EFA\u8BAE"].some((w) => m.includes(w))) return "wants_opinion";
|
|
29
|
+
if (["\u987A\u4FBF", "\u53E6\u5916", "\u8FD8\u6709", "\u5BF9\u4E86"].some((w) => m.includes(w))) return "wants_proactive";
|
|
30
|
+
if (m.endsWith("?") || m.endsWith("\uFF1F") || ["\u5417", "\u5462", "\u4E48"].some((w) => m.endsWith(w))) return "wants_answer";
|
|
31
|
+
if (msg.length < 20) return "wants_quick";
|
|
32
|
+
if (["\u505A", "\u5199", "\u6539", "\u5E2E\u6211", "\u5B9E\u73B0", "\u751F\u6210"].some((w) => m.includes(w))) return "wants_action";
|
|
33
|
+
return "unclear";
|
|
34
|
+
}
|
|
35
|
+
__name(detectIntent, "detectIntent");
|
|
36
|
+
function decideStrategy(attention, intent, msgLen) {
|
|
37
|
+
if (attention.type === "correction") return "acknowledge_and_retry";
|
|
38
|
+
if (attention.type === "emotional") return "empathy_first";
|
|
39
|
+
if (intent === "wants_quick" || msgLen < 10) return "direct";
|
|
40
|
+
if (intent === "wants_opinion") return "opinion_with_reasoning";
|
|
41
|
+
if (intent === "wants_action") return "action_oriented";
|
|
42
|
+
if (msgLen > 200) return "detailed";
|
|
43
|
+
return "balanced";
|
|
44
|
+
}
|
|
45
|
+
__name(decideStrategy, "decideStrategy");
|
|
46
|
+
function detectImplicitFeedbackSync(msg, prevResponse) {
|
|
47
|
+
if (!prevResponse) return null;
|
|
48
|
+
const m = msg.toLowerCase();
|
|
49
|
+
if (prevResponse.length > 500 && msg.length < 10 && ["\u55EF", "\u597D", "\u884C", "\u54E6", "ok"].some((w) => m.includes(w))) {
|
|
50
|
+
return "too_verbose";
|
|
51
|
+
}
|
|
52
|
+
if (["\u55EF", "\u597D\u7684", "\u660E\u767D", "\u4E86\u89E3", "ok", "\u6536\u5230", "\u53EF\u4EE5", "\u597D"].some((w) => m === w)) {
|
|
53
|
+
return "silent_accept";
|
|
54
|
+
}
|
|
55
|
+
if (["\u592A\u597D\u4E86", "\u725B", "\u5389\u5BB3", "\u5B8C\u7F8E", "\u6B63\u662F", "\u5BF9\u5BF9\u5BF9", "\u5C31\u662F\u8FD9\u4E2A", "\u611F\u8C22"].some((w) => m.includes(w))) {
|
|
56
|
+
return "positive";
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
__name(detectImplicitFeedbackSync, "detectImplicitFeedbackSync");
|
|
61
|
+
function predictIntent(msg, _senderId, lastMsgs) {
|
|
62
|
+
const hints = [];
|
|
63
|
+
const m = msg.toLowerCase();
|
|
64
|
+
if (lastMsgs.length >= 2 && lastMsgs.slice(-2).every((x) => x.length < 50) && msg.length < 50) {
|
|
65
|
+
hints.push("\u7528\u6237\u5728\u8FDE\u7EED\u53D1\u77ED\u6D88\u606F\u63CF\u8FF0\u95EE\u9898\uFF0C\u7B49\u4ED6\u8BF4\u5B8C\u518D\u56DE\u590D\uFF0C\u4E0D\u8981\u9010\u6761\u56DE");
|
|
66
|
+
}
|
|
67
|
+
if (m === "?" || m === "\uFF1F" || m === "..." || m === "???") {
|
|
68
|
+
hints.push("\u7528\u6237\u5728\u50AC\u56DE\u590D\uFF0C\u7B80\u77ED\u56DE\u5E94\u5373\u53EF");
|
|
69
|
+
}
|
|
70
|
+
if (msg.includes("[\u56FE\u7247]") || msg.includes("[Image]") || msg.includes("\u622A\u56FE")) {
|
|
71
|
+
hints.push("\u7528\u6237\u53D1\u4E86\u56FE\u7247/\u622A\u56FE\uFF0C\u5173\u6CE8\u5185\u5BB9\u672C\u8EAB\uFF0C\u4E0D\u8981\u8BC4\u4EF7\u56FE\u7247\u8D28\u91CF");
|
|
72
|
+
}
|
|
73
|
+
if (msg.includes("[\u8F6C\u53D1]") || msg.includes("\u8F6C\u53D1") || msg.startsWith(">>")) {
|
|
74
|
+
hints.push("\u8FD9\u662F\u8F6C\u53D1\u7684\u5185\u5BB9\uFF0C\u7528\u6237\u60F3\u8981\u4F60\u7684\u5206\u6790/\u770B\u6CD5");
|
|
75
|
+
}
|
|
76
|
+
if (msg.includes("```") || msg.includes("error") || msg.includes("Error") || msg.includes("traceback")) {
|
|
77
|
+
hints.push("\u7528\u6237\u8D34\u4E86\u4EE3\u7801/\u9519\u8BEF\u4FE1\u606F\uFF0C\u76F4\u63A5\u5B9A\u4F4D\u95EE\u9898\u7ED9\u89E3\u51B3\u65B9\u6848");
|
|
78
|
+
}
|
|
79
|
+
if (msg.length > 200 && (msg.match(/\d+/g) || []).length > 5) {
|
|
80
|
+
hints.push("\u6D88\u606F\u5305\u542B\u5927\u91CF\u6570\u636E/\u6570\u5B57\uFF0C\u505A\u5206\u6790\u800C\u4E0D\u662F\u6458\u8981");
|
|
81
|
+
}
|
|
82
|
+
return hints;
|
|
83
|
+
}
|
|
84
|
+
__name(predictIntent, "predictIntent");
|
|
85
|
+
function cogProcess(msg, lastResponseContent, lastPrompt, senderId) {
|
|
86
|
+
const attention = attentionGate(msg);
|
|
87
|
+
const intent = detectIntent(msg);
|
|
88
|
+
const complexity = Math.min(1, msg.length / 500);
|
|
89
|
+
const strategy = decideStrategy(attention, intent, msg.length);
|
|
90
|
+
const hints = [];
|
|
91
|
+
if (attention.type === "correction") {
|
|
92
|
+
const profile = senderId ? getProfile(senderId) : null;
|
|
93
|
+
const tier = profile?.tier || "new";
|
|
94
|
+
if (tier === "owner") {
|
|
95
|
+
hints.push("\u26A0 \u4E3B\u4EBA\u5728\u7EA0\u6B63\u4F60\uFF0C\u8FD9\u662F\u9AD8\u6743\u91CD\u53CD\u9988\uFF0C\u5FC5\u987B\u8BA4\u771F\u5BF9\u5F85\u5E76\u8C03\u6574");
|
|
96
|
+
bodyOnCorrection();
|
|
97
|
+
} else if (tier === "known") {
|
|
98
|
+
hints.push("\u26A0 \u8001\u670B\u53CB\u5728\u7EA0\u6B63\u4F60\uFF0C\u6CE8\u610F\u8C03\u6574");
|
|
99
|
+
body.alertness = Math.min(1, body.alertness + 0.1);
|
|
100
|
+
body.mood = Math.max(-1, body.mood - 0.05);
|
|
101
|
+
} else {
|
|
102
|
+
hints.push("\u65B0\u7528\u6237\u53CD\u9988\uFF0C\u53EF\u80FD\u662F\u671F\u671B\u7BA1\u7406\u95EE\u9898\uFF0C\u6E29\u548C\u5BF9\u5F85");
|
|
103
|
+
body.alertness = Math.min(1, body.alertness + 0.05);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (attention.type === "emotional") {
|
|
107
|
+
const neg = ["\u70E6", "\u7D2F", "\u96BE\u8FC7", "\u5D29\u6E83", "\u538B\u529B", "\u7126\u8651"].some((w) => msg.includes(w));
|
|
108
|
+
if (neg) {
|
|
109
|
+
hints.push("\u7528\u6237\u60C5\u7EEA\u4E0D\u597D\uFF0C\u5148\u5171\u60C5\u518D\u56DE\u7B54\uFF0C\u4E0D\u8981\u6025\u7740\u7ED9\u5EFA\u8BAE");
|
|
110
|
+
body.mood = Math.max(-1, body.mood - 0.15);
|
|
111
|
+
} else {
|
|
112
|
+
hints.push("\u7528\u6237\u60C5\u7EEA\u79EF\u6781\uFF0C\u53EF\u4EE5\u8F7B\u677E\u4E92\u52A8");
|
|
113
|
+
body.mood = Math.min(1, body.mood + 0.1);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (strategy === "direct") hints.push("\u7B80\u77ED\u56DE\u7B54\u5373\u53EF");
|
|
117
|
+
if (strategy === "opinion_with_reasoning") hints.push('\u7ED9\u51FA\u660E\u786E\u7ACB\u573A\u548C\u7406\u7531\uFF0C\u4E0D\u8BF4"\u5404\u6709\u4F18\u52A3"');
|
|
118
|
+
if (strategy === "action_oriented") hints.push("\u5148\u7ED9\u4EE3\u7801/\u65B9\u6848\uFF0C\u518D\u89E3\u91CA");
|
|
119
|
+
if (strategy === "empathy_first") hints.push("\u5148\u5171\u60C5\uFF0C\u518D\u63D0\u4F9B\u5E2E\u52A9");
|
|
120
|
+
if (strategy === "acknowledge_and_retry") hints.push("\u5148\u627F\u8BA4\u9519\u8BEF\uFF0C\u518D\u7ED9\u51FA\u6B63\u786E\u7B54\u6848");
|
|
121
|
+
const implicit = detectImplicitFeedbackSync(msg, lastResponseContent);
|
|
122
|
+
if (implicit === "too_verbose") {
|
|
123
|
+
body.energy = Math.max(0, body.energy - 0.03);
|
|
124
|
+
hints.push("\u4E0A\u6B21\u56DE\u7B54\u53EF\u80FD\u592A\u957F\u4E86\uFF0C\u8FD9\u6B21\u7B80\u6D01\u4E9B");
|
|
125
|
+
} else if (implicit === "silent_accept") {
|
|
126
|
+
} else if (implicit === "positive") {
|
|
127
|
+
bodyOnPositiveFeedback();
|
|
128
|
+
}
|
|
129
|
+
if (senderId) {
|
|
130
|
+
const tier = getProfileTier(senderId);
|
|
131
|
+
if (tier === "owner") {
|
|
132
|
+
hints.push("\u4E3B\u4EBA\u5728\u8BF4\u8BDD\uFF0C\u6280\u672F\u6DF1\u5EA6\u4F18\u5148\uFF0C\u5C11\u5E9F\u8BDD");
|
|
133
|
+
} else if (tier === "new") {
|
|
134
|
+
hints.push("\u65B0\u7528\u6237\uFF0C\u8010\u5FC3\u89C2\u5BDF\uFF0C\u5148\u4E86\u89E3\u5BF9\u65B9\u518D\u9002\u914D\u98CE\u683C");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return { hints, intent, strategy, attention: attention.type, complexity };
|
|
138
|
+
}
|
|
139
|
+
__name(cogProcess, "cogProcess");
|
|
140
|
+
export {
|
|
141
|
+
cogProcess,
|
|
142
|
+
predictIntent
|
|
143
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{existsSync,readFileSync}from"fs";const MAX_FILES=2,INLINE_LIMIT=2e3,HEAD_LINES=50;function prepareContext(e){const r=[],t=(e.match(/(?:~\/|\/[\w.-]+)[\w./-]*\.[\w]+/g)||[]).map(e=>e.startsWith("~/")?e.replace("~",process.env.HOME||""):e).slice(0,2);for(const e of t)try{if(!existsSync(e))continue;const t=readFileSync(e,"utf-8");if(t.length<=2e3)r.push({content:`[文件内容: ${e}]\n${t}`,source:e});else{const n=t.split("\n"),o=n.slice(0,50).join("\n");r.push({content:`[文件内容: ${e}] (${n.length}行, 前50行)\n${o}`,source:e})}}catch{}const n=e.match(/(?:Error|错误|error|FAIL|panic|Exception|TypeError|ReferenceError|SyntaxError)[::]\s*(.{10,120})/i);return n&&r.push({content:`[错误信息提取] ${n[1].trim()}`,source:"error-detect"}),/0x[0-9a-f]{6,}/i.test(e)&&r.push({content:"[检测到内存地址] 用户可能在做逆向/调试,注意地址格式和偏移量",source:"hex-detect"}),r}export{prepareContext};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{resolve}from"path";import{DATA_DIR,loadJson,debouncedSave}from"./persistence.ts";const EPISTEMIC_PATH=resolve(DATA_DIR,"epistemic.json"),domains=new Map;function detectDomain(o){const n=o.toLowerCase();return["frida","hook","ida","mach-o","dyld","arm64","objc","逆向","砸壳","tweak","substrate","theos"].some(o=>n.includes(o))?"ios-reverse":["swift","xcode","swiftui","uikit","cocoa","appkit"].some(o=>n.includes(o))?"swift":["python","pip","flask","django","def ","import ",".py","asyncio","pandas"].some(o=>n.includes(o))?"python":["typescript","javascript","node","react","vue",".ts",".js","npm","pnpm","bun"].some(o=>n.includes(o))?"javascript":["docker","k8s","kubernetes","nginx","linux","bash","shell","systemd","ssh"].some(o=>n.includes(o))?"devops":["sql","mysql","postgres","mongodb","数据库","redis","sqlite"].some(o=>n.includes(o))?"database":["图片","ocr","识别","照片","截图","看看这个","这张图"].some(o=>n.includes(o))?"图片识别":["git","github","pr","merge","branch","commit","rebase"].some(o=>n.includes(o))?"git":["rust","cargo",".rs","lifetime","borrow checker"].some(o=>n.includes(o))?"rust":["go ","golang","goroutine",".go","func "].some(o=>n.includes(o))?"golang":o.length<20?"闲聊":["怎么看","你觉得","建议","应该","推荐"].some(o=>n.includes(o))?"咨询":"通用"}function loadEpistemic(){const o=loadJson(EPISTEMIC_PATH,{});domains.clear();for(const[n,e]of Object.entries(o))domains.set(n,e);console.log(`[cc-soul][epistemic] loaded ${domains.size} domains`)}function saveEpistemic(){const o={};for(const[n,e]of domains)o[n]=e;debouncedSave(EPISTEMIC_PATH,o)}function ensureDomain(o){let n=domains.get(o);return n||(n={domain:o,o:0,t:0,i:0,m:5,u:0},domains.set(o,n)),n}function recompute(o){o.m=o.o>0?Math.round(o.t/o.o*10)/10:5,o.u=o.o>0?Math.round(o.i/o.o*1e3)/10:0}function trackDomainQuality(o,n){const e=ensureDomain(detectDomain(o));e.o++,e.t+=n,recompute(e),saveEpistemic()}function trackDomainCorrection(o){const n=ensureDomain(detectDomain(o));n.i++,recompute(n),saveEpistemic()}function getDomainConfidence(o){const n=detectDomain(o),e=domains.get(n);return!e||e.o<3?{domain:n,p:"medium",hint:""}:e.u>10&&e.o>=5?{domain:n,p:"low",hint:`[知识边界] "${n}" 领域纠正率 ${e.u}%,这个领域我不太确定,你验证一下`}:e.m<5&&e.o>=5?{domain:n,p:"low",hint:`[知识边界] "${n}" 领域平均质量 ${e.m}/10,我在这方面表现不佳,请仔细核实`}:e.m>7&&e.o>=10?{domain:n,p:"high",hint:""}:{domain:n,p:"medium",hint:""}}function getWeakDomains(){return[...domains.values()].filter(o=>o.o>=5&&(o.u>10||o.m<5)).sort((o,n)=>n.u-o.u).map(o=>o.domain)}function getEpistemicSummary(){if(0===domains.size)return"";const o=[...domains.values()].filter(o=>o.o>=3).sort((o,n)=>n.o-o.o);if(0===o.length)return"";const n=[],e=o.filter(o=>o.u>10&&o.o>=5||o.m<5&&o.o>=5);if(e.length>0){n.push("⚠ 薄弱领域(回答前要格外谨慎):");for(const o of e)n.push(`- ${o.domain}: 质量${o.m}/10, 纠正率${o.u}%, 样本${o.o}`)}const t=o.filter(o=>o.m>7&&o.o>=10);if(t.length>0){n.push("✓ 擅长领域:");for(const o of t)n.push(`- ${o.domain}: 质量${o.m}/10, 样本${o.o}`)}return n.join("\n")}export{detectDomain,getDomainConfidence,getEpistemicSummary,getWeakDomains,loadEpistemic,trackDomainCorrection,trackDomainQuality};
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { createHash } from "crypto";
|
|
4
|
+
import { RULES_PATH, HYPOTHESES_PATH, loadJson, debouncedSave } from "./persistence.ts";
|
|
5
|
+
import { addMemory } from "./memory.ts";
|
|
6
|
+
import { notifySoulActivity } from "./notify.ts";
|
|
7
|
+
import { spawnCLI } from "./cli.ts";
|
|
8
|
+
const MAX_RULES = 50;
|
|
9
|
+
let rules = [];
|
|
10
|
+
let hypotheses = [];
|
|
11
|
+
function md5(s) {
|
|
12
|
+
return createHash("md5").update(s).digest("hex").slice(0, 16);
|
|
13
|
+
}
|
|
14
|
+
__name(md5, "md5");
|
|
15
|
+
function loadRules() {
|
|
16
|
+
rules = loadJson(RULES_PATH, []);
|
|
17
|
+
}
|
|
18
|
+
__name(loadRules, "loadRules");
|
|
19
|
+
function saveRules() {
|
|
20
|
+
debouncedSave(RULES_PATH, rules);
|
|
21
|
+
}
|
|
22
|
+
__name(saveRules, "saveRules");
|
|
23
|
+
function addRule(rule, source) {
|
|
24
|
+
if (!rule || rule.length < 5) return;
|
|
25
|
+
if (rules.some((r) => r.rule === rule)) return;
|
|
26
|
+
rules.push({ rule, source: source.slice(0, 100), ts: Date.now(), hits: 0 });
|
|
27
|
+
if (rules.length > MAX_RULES) {
|
|
28
|
+
rules.sort((a, b) => b.hits * 10 + b.ts / 1e10 - (a.hits * 10 + a.ts / 1e10));
|
|
29
|
+
rules = rules.slice(0, MAX_RULES);
|
|
30
|
+
}
|
|
31
|
+
saveRules();
|
|
32
|
+
}
|
|
33
|
+
__name(addRule, "addRule");
|
|
34
|
+
function getRelevantRules(msg, topN = 3) {
|
|
35
|
+
if (rules.length === 0) return [];
|
|
36
|
+
const msgWords = new Set((msg.match(/[\u4e00-\u9fff]{2,}|[a-z]{3,}/gi) || []).map((w) => w.toLowerCase()));
|
|
37
|
+
if (msgWords.size === 0) return rules.slice(0, topN);
|
|
38
|
+
const scored = rules.map((r) => {
|
|
39
|
+
const ruleWords = (r.rule.match(/[\u4e00-\u9fff]{2,}|[a-z]{3,}/gi) || []).map((w) => w.toLowerCase());
|
|
40
|
+
const overlap = ruleWords.filter((w) => msgWords.has(w)).length;
|
|
41
|
+
return { ...r, score: overlap + r.hits * 0.1 };
|
|
42
|
+
});
|
|
43
|
+
scored.sort((a, b) => b.score - a.score);
|
|
44
|
+
const relevant = scored.filter((r) => r.score > 0).slice(0, topN);
|
|
45
|
+
for (const r of relevant) {
|
|
46
|
+
const orig = rules.find((o) => o.rule === r.rule);
|
|
47
|
+
if (orig) orig.hits++;
|
|
48
|
+
}
|
|
49
|
+
return relevant;
|
|
50
|
+
}
|
|
51
|
+
__name(getRelevantRules, "getRelevantRules");
|
|
52
|
+
function loadHypotheses() {
|
|
53
|
+
hypotheses = loadJson(HYPOTHESES_PATH, []);
|
|
54
|
+
}
|
|
55
|
+
__name(loadHypotheses, "loadHypotheses");
|
|
56
|
+
function formHypothesis(pattern, observation) {
|
|
57
|
+
const id = md5(pattern);
|
|
58
|
+
if (hypotheses.some((h) => h.id === id)) return;
|
|
59
|
+
hypotheses.push({
|
|
60
|
+
id,
|
|
61
|
+
description: `\u5F53\u9047\u5230"${pattern.slice(0, 30)}"\u65F6: ${observation.slice(0, 60)}`,
|
|
62
|
+
evidence_for: 1,
|
|
63
|
+
evidence_against: 0,
|
|
64
|
+
status: "active",
|
|
65
|
+
created: Date.now()
|
|
66
|
+
});
|
|
67
|
+
if (hypotheses.length > 30) {
|
|
68
|
+
hypotheses = hypotheses.filter((h) => h.status !== "rejected").sort((a, b) => b.evidence_for - b.evidence_against - (a.evidence_for - a.evidence_against)).slice(0, 25);
|
|
69
|
+
}
|
|
70
|
+
debouncedSave(HYPOTHESES_PATH, hypotheses);
|
|
71
|
+
console.log(`[cc-soul][evolve] \u65B0\u5047\u8BBE: ${pattern.slice(0, 30)} \u2192 ${observation.slice(0, 40)}`);
|
|
72
|
+
notifySoulActivity(`\u{1F9EC} \u65B0\u5047\u8BBE: ${pattern.slice(0, 30)} \u2192 ${observation.slice(0, 40)}`).catch(() => {
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
__name(formHypothesis, "formHypothesis");
|
|
76
|
+
function verifyHypothesis(situation, wasCorrect) {
|
|
77
|
+
for (const h of hypotheses) {
|
|
78
|
+
if (h.status === "rejected") continue;
|
|
79
|
+
const keywords = h.description.match(/[\u4e00-\u9fff]{2,}|[a-z]{3,}/gi) || [];
|
|
80
|
+
const matches = keywords.filter((w) => situation.toLowerCase().includes(w.toLowerCase())).length;
|
|
81
|
+
if (matches < 2) continue;
|
|
82
|
+
if (wasCorrect) {
|
|
83
|
+
h.evidence_for++;
|
|
84
|
+
if (h.evidence_for >= 5 && h.status === "active") {
|
|
85
|
+
h.status = "verified";
|
|
86
|
+
addRule(h.description, "hypothesis_verified");
|
|
87
|
+
console.log(`[cc-soul][evolve] \u5047\u8BBE\u9A8C\u8BC1\u901A\u8FC7 \u2192 \u89C4\u5219: ${h.description.slice(0, 40)}`);
|
|
88
|
+
notifySoulActivity(`\u2705 \u5047\u8BBE\u9A8C\u8BC1: ${h.description.slice(0, 40)}`).catch(() => {
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
h.evidence_against++;
|
|
93
|
+
if (h.evidence_against >= 3) {
|
|
94
|
+
h.status = "rejected";
|
|
95
|
+
console.log(`[cc-soul][evolve] \u5047\u8BBE\u88AB\u5426\u5B9A: ${h.description.slice(0, 40)}`);
|
|
96
|
+
notifySoulActivity(`\u274C \u5047\u8BBE\u5426\u5B9A: ${h.description.slice(0, 40)}`).catch(() => {
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
debouncedSave(HYPOTHESES_PATH, hypotheses);
|
|
102
|
+
}
|
|
103
|
+
__name(verifyHypothesis, "verifyHypothesis");
|
|
104
|
+
function onCorrectionEvolution(userMsg) {
|
|
105
|
+
const patterns = [
|
|
106
|
+
/不要(.{2,30})/,
|
|
107
|
+
/别(.{2,20})/,
|
|
108
|
+
/应该(.{2,30})/,
|
|
109
|
+
/正确的是(.{2,30})/
|
|
110
|
+
];
|
|
111
|
+
for (const p of patterns) {
|
|
112
|
+
const m = userMsg.match(p);
|
|
113
|
+
if (m) {
|
|
114
|
+
addRule(m[0], userMsg.slice(0, 80));
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
addMemory(`\u7EA0\u6B63: ${userMsg.slice(0, 60)}`, "correction");
|
|
119
|
+
}
|
|
120
|
+
__name(onCorrectionEvolution, "onCorrectionEvolution");
|
|
121
|
+
function onCorrectionAdvanced(userMsg, lastResponse) {
|
|
122
|
+
onCorrectionEvolution(userMsg);
|
|
123
|
+
const causalPatterns = [
|
|
124
|
+
{ pattern: /太长|太啰嗦|简洁/, cause: "\u56DE\u7B54\u592A\u5197\u957F\uFF0C\u7528\u6237\u8981\u7B80\u6D01" },
|
|
125
|
+
{ pattern: /跑偏|离题|不是问/, cause: "\u7406\u89E3\u504F\u4E86\uFF0C\u6CA1\u56DE\u7B54\u5230\u70B9\u4E0A" },
|
|
126
|
+
{ pattern: /不准|不对|错误/, cause: "\u4FE1\u606F\u4E0D\u51C6\u786E" },
|
|
127
|
+
{ pattern: /口气|语气|态度/, cause: "\u8BED\u6C14\u4E0D\u5BF9" },
|
|
128
|
+
{ pattern: /太简单|没深度|浅/, cause: "\u56DE\u7B54\u592A\u6D45" }
|
|
129
|
+
];
|
|
130
|
+
for (const { pattern, cause } of causalPatterns) {
|
|
131
|
+
if (pattern.test(userMsg)) {
|
|
132
|
+
formHypothesis(userMsg.slice(0, 50), cause);
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
verifyHypothesis(lastResponse, false);
|
|
137
|
+
}
|
|
138
|
+
__name(onCorrectionAdvanced, "onCorrectionAdvanced");
|
|
139
|
+
function attributeCorrection(userMsg, lastResponse, augmentsUsed) {
|
|
140
|
+
spawnCLI(
|
|
141
|
+
`\u4E0A\u4E00\u6B21\u56DE\u590D: "${lastResponse.slice(0, 300)}"
|
|
142
|
+
\u6CE8\u5165\u7684\u4E0A\u4E0B\u6587: ${augmentsUsed.slice(0, 3).join("; ").slice(0, 200)}
|
|
143
|
+
\u7528\u6237\u7EA0\u6B63: "${userMsg.slice(0, 200)}"
|
|
144
|
+
|
|
145
|
+
\u5224\u65AD\u56DE\u590D\u51FA\u9519\u7684\u539F\u56E0\uFF08\u53EA\u9009\u4E00\u4E2A\uFF09:
|
|
146
|
+
1=\u6A21\u578B\u5E7B\u89C9 2=\u8BB0\u5FC6\u8BEF\u5BFC 3=\u89C4\u5219\u51B2\u7A81 4=\u7406\u89E3\u504F\u5DEE 5=\u9886\u57DF\u4E0D\u8DB3
|
|
147
|
+
\u683C\u5F0F: {"cause":N,"detail":"\u4E00\u53E5\u8BDD"}`,
|
|
148
|
+
(output) => {
|
|
149
|
+
try {
|
|
150
|
+
const m = output.match(/\{[\s\S]*?\}/);
|
|
151
|
+
if (m) {
|
|
152
|
+
const result = JSON.parse(m[0]);
|
|
153
|
+
const causeNames = ["", "\u6A21\u578B\u5E7B\u89C9", "\u8BB0\u5FC6\u8BEF\u5BFC", "\u89C4\u5219\u51B2\u7A81", "\u7406\u89E3\u504F\u5DEE", "\u9886\u57DF\u4E0D\u8DB3"];
|
|
154
|
+
const causeName = causeNames[result.cause] || "\u672A\u77E5";
|
|
155
|
+
console.log(`[cc-soul][attribution] cause=${causeName}: ${result.detail}`);
|
|
156
|
+
addMemory(`[\u7EA0\u6B63\u5F52\u56E0] ${causeName}: ${result.detail}`, "correction");
|
|
157
|
+
}
|
|
158
|
+
} catch (e) {
|
|
159
|
+
console.error(`[cc-soul][attribution] parse error: ${e.message}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
__name(attributeCorrection, "attributeCorrection");
|
|
165
|
+
export {
|
|
166
|
+
addRule,
|
|
167
|
+
attributeCorrection,
|
|
168
|
+
formHypothesis,
|
|
169
|
+
getRelevantRules,
|
|
170
|
+
hypotheses,
|
|
171
|
+
loadHypotheses,
|
|
172
|
+
loadRules,
|
|
173
|
+
onCorrectionAdvanced,
|
|
174
|
+
rules,
|
|
175
|
+
verifyHypothesis
|
|
176
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { FEATURES_PATH, loadJson, saveJson } from "./persistence.ts";
|
|
4
|
+
const DEFAULTS = {
|
|
5
|
+
memory_active: true,
|
|
6
|
+
memory_consolidation: true,
|
|
7
|
+
memory_contradiction_scan: true,
|
|
8
|
+
memory_tags: true,
|
|
9
|
+
memory_associative_recall: true,
|
|
10
|
+
memory_predictive: true,
|
|
11
|
+
memory_session_summary: true,
|
|
12
|
+
lorebook: true,
|
|
13
|
+
skill_library: true,
|
|
14
|
+
persona_splitting: true,
|
|
15
|
+
emotional_contagion: true,
|
|
16
|
+
fingerprint: true,
|
|
17
|
+
metacognition: true,
|
|
18
|
+
dream_mode: true,
|
|
19
|
+
autonomous_voice: true,
|
|
20
|
+
web_rover: true,
|
|
21
|
+
structured_reflection: true,
|
|
22
|
+
plan_tracking: true,
|
|
23
|
+
self_upgrade: false,
|
|
24
|
+
// 默认关闭 — 用户需要显式开启才能让 cc 改自己的代码
|
|
25
|
+
federation: true,
|
|
26
|
+
sync: true
|
|
27
|
+
};
|
|
28
|
+
let features = { ...DEFAULTS };
|
|
29
|
+
function loadFeatures() {
|
|
30
|
+
const loaded = loadJson(FEATURES_PATH, {});
|
|
31
|
+
features = { ...DEFAULTS, ...loaded };
|
|
32
|
+
saveJson(FEATURES_PATH, features);
|
|
33
|
+
const on = Object.values(features).filter((v) => v).length;
|
|
34
|
+
const total = Object.keys(features).length;
|
|
35
|
+
console.log(`[cc-soul][features] ${on}/${total} features enabled`);
|
|
36
|
+
}
|
|
37
|
+
__name(loadFeatures, "loadFeatures");
|
|
38
|
+
function isEnabled(feature) {
|
|
39
|
+
return features[feature] ?? true;
|
|
40
|
+
}
|
|
41
|
+
__name(isEnabled, "isEnabled");
|
|
42
|
+
function setFeature(feature, enabled) {
|
|
43
|
+
features[feature] = enabled;
|
|
44
|
+
saveJson(FEATURES_PATH, features);
|
|
45
|
+
console.log(`[cc-soul][features] ${feature} \u2192 ${enabled ? "ON" : "OFF"}`);
|
|
46
|
+
}
|
|
47
|
+
__name(setFeature, "setFeature");
|
|
48
|
+
function getAllFeatures() {
|
|
49
|
+
return { ...features };
|
|
50
|
+
}
|
|
51
|
+
__name(getAllFeatures, "getAllFeatures");
|
|
52
|
+
function handleFeatureCommand(msg) {
|
|
53
|
+
const m = msg.trim();
|
|
54
|
+
if (m === "\u529F\u80FD\u72B6\u6001" || m === "features" || m === "feature status") {
|
|
55
|
+
const lines = Object.entries(features).map(([k, v]) => ` ${v ? "\u2705" : "\u274C"} ${k}`).join("\n");
|
|
56
|
+
console.log(`[cc-soul][features] status:
|
|
57
|
+
${lines}`);
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
const onMatch = m.match(/^(?:开启|启用|enable)\s+(\S+)$/);
|
|
61
|
+
if (onMatch && onMatch[1] in features) {
|
|
62
|
+
setFeature(onMatch[1], true);
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
const offMatch = m.match(/^(?:关闭|禁用|disable)\s+(\S+)$/);
|
|
66
|
+
if (offMatch && offMatch[1] in features) {
|
|
67
|
+
setFeature(offMatch[1], false);
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
__name(handleFeatureCommand, "handleFeatureCommand");
|
|
73
|
+
export {
|
|
74
|
+
getAllFeatures,
|
|
75
|
+
handleFeatureCommand,
|
|
76
|
+
isEnabled,
|
|
77
|
+
loadFeatures,
|
|
78
|
+
setFeature
|
|
79
|
+
};
|