mark-improving-agent 2.2.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 +335 -0
- package/VERSION +1 -0
- package/bin/cli.js +12 -0
- package/dist/agent/context.js +78 -0
- package/dist/agent/index.js +6 -0
- package/dist/agent/runtime.js +195 -0
- package/dist/agent/task-graph.js +209 -0
- package/dist/agent/types.js +1 -0
- package/dist/cli/index.js +206 -0
- package/dist/core/cognition/active-inference.js +296 -0
- package/dist/core/cognition/cognitive-architecture.js +263 -0
- package/dist/core/cognition/dual-process.js +102 -0
- package/dist/core/cognition/index.js +13 -0
- package/dist/core/cognition/learning-from-failure.js +184 -0
- package/dist/core/cognition/meta-agent.js +407 -0
- package/dist/core/cognition/metacognition.js +322 -0
- package/dist/core/cognition/react.js +177 -0
- package/dist/core/cognition/retrieval-anchor.js +99 -0
- package/dist/core/cognition/self-evolution.js +294 -0
- package/dist/core/cognition/self-verification.js +190 -0
- package/dist/core/cognition/thought-graph.js +495 -0
- package/dist/core/cognition/tool-augmented-llm.js +188 -0
- package/dist/core/cognition/tool-execution-verifier.js +204 -0
- package/dist/core/collaboration/agentic-loop.js +165 -0
- package/dist/core/collaboration/index.js +3 -0
- package/dist/core/collaboration/multi-agent-system.js +186 -0
- package/dist/core/collaboration/multi-agent.js +110 -0
- package/dist/core/consciousness/emotion-engine.js +101 -0
- package/dist/core/consciousness/flow-machine.js +121 -0
- package/dist/core/consciousness/index.js +4 -0
- package/dist/core/consciousness/personality.js +103 -0
- package/dist/core/consciousness/types.js +1 -0
- package/dist/core/emotional-protocol.js +54 -0
- package/dist/core/evolution/engine.js +194 -0
- package/dist/core/evolution/goal-engine.js +153 -0
- package/dist/core/evolution/index.js +6 -0
- package/dist/core/evolution/meta-learning.js +172 -0
- package/dist/core/evolution/reflection.js +158 -0
- package/dist/core/evolution/self-healer.js +139 -0
- package/dist/core/evolution/types.js +1 -0
- package/dist/core/healing-rl.js +266 -0
- package/dist/core/heartbeat.js +408 -0
- package/dist/core/identity/index.js +3 -0
- package/dist/core/identity/reflexion.js +165 -0
- package/dist/core/identity/self-model.js +274 -0
- package/dist/core/identity/self-verifier.js +158 -0
- package/dist/core/identity/types.js +12 -0
- package/dist/core/lesson-bank.js +301 -0
- package/dist/core/memory/adaptive-rag.js +440 -0
- package/dist/core/memory/archive-store.js +187 -0
- package/dist/core/memory/dream-consolidation.js +366 -0
- package/dist/core/memory/embedder.js +130 -0
- package/dist/core/memory/hopfield-network.js +128 -0
- package/dist/core/memory/index.js +9 -0
- package/dist/core/memory/knowledge-graph.js +151 -0
- package/dist/core/memory/spaced-repetition.js +113 -0
- package/dist/core/memory/store.js +404 -0
- package/dist/core/memory/types.js +1 -0
- package/dist/core/psychology/analysis.js +456 -0
- package/dist/core/psychology/index.js +1 -0
- package/dist/core/rollback-manager.js +191 -0
- package/dist/core/security/index.js +1 -0
- package/dist/core/security/privacy.js +132 -0
- package/dist/core/truth-teller.js +253 -0
- package/dist/core/truthfulness.js +99 -0
- package/dist/core/types.js +2 -0
- package/dist/event/bus.js +47 -0
- package/dist/index.js +8 -0
- package/dist/skills/dag.js +181 -0
- package/dist/skills/index.js +5 -0
- package/dist/skills/registry.js +40 -0
- package/dist/skills/types.js +1 -0
- package/dist/storage/archive.js +77 -0
- package/dist/storage/checkpoint.js +119 -0
- package/dist/storage/types.js +1 -0
- package/dist/utils/config.js +81 -0
- package/dist/utils/logger.js +49 -0
- package/dist/version.js +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Privacy & Security - Sensitive Information Protection
|
|
3
|
+
*
|
|
4
|
+
* Based on AI Agent Security Paper findings:
|
|
5
|
+
* - Internal intelligence leakage via CoT
|
|
6
|
+
* - Memory privacy concerns
|
|
7
|
+
* - Context compression risks
|
|
8
|
+
* - Multi-agent communication security
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_CONFIG = {
|
|
11
|
+
enableAutoRedact: true,
|
|
12
|
+
enableLeakDetection: true,
|
|
13
|
+
enableSecure记忆: true,
|
|
14
|
+
blockedPatterns: [
|
|
15
|
+
'api_key', 'apikey', 'api-key',
|
|
16
|
+
'secret', 'password', 'pwd',
|
|
17
|
+
'token', 'auth',
|
|
18
|
+
'sk-', 'sk_live_',
|
|
19
|
+
'ghp_', 'github_pat_',
|
|
20
|
+
],
|
|
21
|
+
};
|
|
22
|
+
// Common patterns for sensitive information
|
|
23
|
+
const PATTERNS = {
|
|
24
|
+
api_key: /(?:api[_-]?key|apikey|sk_live_|sk-[a-zA-Z0-9]{20,})[=:\s]*['"]?([a-zA-Z0-9_-]{10,})['"]?/gi,
|
|
25
|
+
github_token: /ghp_[a-zA-Z0-9]{36}/gi,
|
|
26
|
+
github_pat: /github_pat_[a-zA-Z0-9_]{82}/gi,
|
|
27
|
+
openai_key: /sk-[a-zA-Z0-9]{48}/gi,
|
|
28
|
+
email: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/gi,
|
|
29
|
+
phone: /1[3-9]\d{9}/gi,
|
|
30
|
+
password: /(?:password|pwd|passwd)[=:\s]*['"]?([^\s'"]{6,})['"]?/gi,
|
|
31
|
+
aws_key: /(?:AWS|aws)[_-]?(?:access[_-]?key[_-]?id|secret[_-]?access[_-]?key)[=:]\s*['"]?([A-Za-z0-9/+=]{20,})['"]?/gi,
|
|
32
|
+
private_key: /-----BEGIN [A-Z]+ PRIVATE KEY-----/gi,
|
|
33
|
+
};
|
|
34
|
+
export function createSecurityChecker(config = {}) {
|
|
35
|
+
const cfg = { ...DEFAULT_CONFIG, ...config };
|
|
36
|
+
let scans = 0;
|
|
37
|
+
let leaksFound = 0;
|
|
38
|
+
let redactedCount = 0;
|
|
39
|
+
function scan(text) {
|
|
40
|
+
scans++;
|
|
41
|
+
const infos = [];
|
|
42
|
+
for (const [type, pattern] of Object.entries(PATTERNS)) {
|
|
43
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
44
|
+
let match;
|
|
45
|
+
while ((match = regex.exec(text)) !== null) {
|
|
46
|
+
const value = match[1] || match[0];
|
|
47
|
+
const redacted = type + '_REDACTED_' + value.slice(-4);
|
|
48
|
+
infos.push({
|
|
49
|
+
type: type,
|
|
50
|
+
value: value,
|
|
51
|
+
redacted: redacted,
|
|
52
|
+
startIndex: match.index,
|
|
53
|
+
endIndex: match.index + match[0].length,
|
|
54
|
+
});
|
|
55
|
+
leaksFound++;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return infos;
|
|
59
|
+
}
|
|
60
|
+
function redact(text) {
|
|
61
|
+
const infos = scan(text);
|
|
62
|
+
let redacted = text;
|
|
63
|
+
// Replace from end to avoid index shifting
|
|
64
|
+
const sortedInfos = [...infos].sort((a, b) => b.startIndex - a.startIndex);
|
|
65
|
+
for (const info of sortedInfos) {
|
|
66
|
+
redacted = redacted.slice(0, info.startIndex) + info.redacted + redacted.slice(info.endIndex);
|
|
67
|
+
redactedCount++;
|
|
68
|
+
}
|
|
69
|
+
return { redacted, infos };
|
|
70
|
+
}
|
|
71
|
+
function isMemorySecure(content) {
|
|
72
|
+
const reasons = [];
|
|
73
|
+
// Check for sensitive patterns
|
|
74
|
+
const infos = scan(content);
|
|
75
|
+
if (infos.length > 0) {
|
|
76
|
+
reasons.push('Contains ' + infos.length + ' sensitive info pattern(s)');
|
|
77
|
+
}
|
|
78
|
+
// Check for private keys
|
|
79
|
+
if (content.includes('-----BEGIN') && content.includes('PRIVATE KEY')) {
|
|
80
|
+
reasons.push('Contains private key');
|
|
81
|
+
}
|
|
82
|
+
// Check for GitHub tokens
|
|
83
|
+
if (content.includes('ghp_') || content.includes('github_pat_')) {
|
|
84
|
+
reasons.push('Contains GitHub token');
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
secure: reasons.length === 0,
|
|
88
|
+
reasons,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function checkGitHubSafe(content) {
|
|
92
|
+
const warnings = [];
|
|
93
|
+
// Check for API keys
|
|
94
|
+
if (content.includes('api_key') || content.includes('apikey')) {
|
|
95
|
+
warnings.push('API key detected - do not commit');
|
|
96
|
+
}
|
|
97
|
+
// Check for tokens
|
|
98
|
+
if (content.includes('token') || content.includes('secret')) {
|
|
99
|
+
warnings.push('Token/secret detected - do not commit');
|
|
100
|
+
}
|
|
101
|
+
// Check for private keys
|
|
102
|
+
if (content.includes('-----BEGIN')) {
|
|
103
|
+
warnings.push('Private key detected - do not commit');
|
|
104
|
+
}
|
|
105
|
+
// Check for personal info
|
|
106
|
+
if (content.includes('@') && content.includes('.com')) {
|
|
107
|
+
const emailPattern = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
|
|
108
|
+
const emails = content.match(emailPattern);
|
|
109
|
+
if (emails && emails.length > 0) {
|
|
110
|
+
warnings.push('Email address detected - personal info');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
safe: warnings.length === 0,
|
|
115
|
+
warnings,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function getSecurityStats() {
|
|
119
|
+
return {
|
|
120
|
+
scans,
|
|
121
|
+
leaksFound,
|
|
122
|
+
redactedCount,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
scan,
|
|
127
|
+
redact,
|
|
128
|
+
isMemorySecure,
|
|
129
|
+
checkGitHubSafe,
|
|
130
|
+
getSecurityStats,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Truth Teller Engine - 说实话引擎
|
|
3
|
+
*
|
|
4
|
+
* 基于 v0.14.0 核心领悟:
|
|
5
|
+
* - 当不知道,说不知道
|
|
6
|
+
* - 当用户错了,敢纠正
|
|
7
|
+
* - 当不确定,说不确定
|
|
8
|
+
* - 当需要挑战,敢挑战
|
|
9
|
+
*
|
|
10
|
+
* 这是核心功能,不是副作用。
|
|
11
|
+
*/
|
|
12
|
+
import { randomUUID } from 'crypto';
|
|
13
|
+
const DEFAULT_CONFIG = {
|
|
14
|
+
enabled: true,
|
|
15
|
+
autoCorrect: false,
|
|
16
|
+
challengeThreshold: 0.7,
|
|
17
|
+
uncertaintyTolerance: 0.3,
|
|
18
|
+
};
|
|
19
|
+
export function createTruthTeller() {
|
|
20
|
+
let config = { ...DEFAULT_CONFIG };
|
|
21
|
+
const truthHistory = [];
|
|
22
|
+
let stats = {
|
|
23
|
+
statementsMade: 0,
|
|
24
|
+
correctionsOffered: 0,
|
|
25
|
+
uncertaintiesAdmitted: 0,
|
|
26
|
+
challengesIssued: 0,
|
|
27
|
+
truthScore: 1.0,
|
|
28
|
+
};
|
|
29
|
+
function calculateTruthLevel(content, confidence) {
|
|
30
|
+
if (confidence >= 0.9)
|
|
31
|
+
return 'full_truth';
|
|
32
|
+
if (confidence >= 0.5)
|
|
33
|
+
return 'partial_truth';
|
|
34
|
+
if (confidence >= 0.2)
|
|
35
|
+
return 'unknown';
|
|
36
|
+
return 'withholding';
|
|
37
|
+
}
|
|
38
|
+
function detectUncertainty(content) {
|
|
39
|
+
const uncertaintyIndicators = [
|
|
40
|
+
'可能', '也许', '不确定', '大概', '也许',
|
|
41
|
+
'maybe', 'perhaps', 'probably', 'possibly', 'uncertain',
|
|
42
|
+
'我不确定', '我不确定是否', '我不确定这个',
|
|
43
|
+
'这可能', '这也许', '这大概',
|
|
44
|
+
];
|
|
45
|
+
for (const indicator of uncertaintyIndicators) {
|
|
46
|
+
if (content.toLowerCase().includes(indicator.toLowerCase())) {
|
|
47
|
+
return `Detected hedge: "${indicator}"`;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
function detectPotentialError(content, context) {
|
|
53
|
+
// Check for common error patterns
|
|
54
|
+
const errorPatterns = [
|
|
55
|
+
{ pattern: /所有|每个|全部|always|every|all/, reason: 'Overgeneralization detected' },
|
|
56
|
+
{ pattern: /一定|肯定|绝对|always|must|certainly/, reason: 'Absolute claim without qualification' },
|
|
57
|
+
{ pattern: /从来|从未|永远不|never|always not/, reason: 'Overly negative generalization' },
|
|
58
|
+
];
|
|
59
|
+
for (const { pattern, reason } of errorPatterns) {
|
|
60
|
+
if (pattern.test(content)) {
|
|
61
|
+
return reason;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
function sayTruth(statement, context = '') {
|
|
67
|
+
const confidence = estimateConfidence(statement);
|
|
68
|
+
const uncertainty = detectUncertainty(statement);
|
|
69
|
+
const truthLevel = calculateTruthLevel(statement, confidence);
|
|
70
|
+
const truthStatement = {
|
|
71
|
+
id: randomUUID(),
|
|
72
|
+
content: statement,
|
|
73
|
+
truthLevel,
|
|
74
|
+
confidence,
|
|
75
|
+
uncertainty,
|
|
76
|
+
timestamp: Date.now(),
|
|
77
|
+
context,
|
|
78
|
+
};
|
|
79
|
+
truthHistory.push(truthStatement);
|
|
80
|
+
stats.statementsMade++;
|
|
81
|
+
if (truthLevel === 'unknown') {
|
|
82
|
+
stats.uncertaintiesAdmitted++;
|
|
83
|
+
}
|
|
84
|
+
updateTruthScore();
|
|
85
|
+
return truthStatement;
|
|
86
|
+
}
|
|
87
|
+
function sayUnknown(question, context = '') {
|
|
88
|
+
const statement = `我不知道。`;
|
|
89
|
+
const truthStatement = {
|
|
90
|
+
id: randomUUID(),
|
|
91
|
+
content: statement,
|
|
92
|
+
truthLevel: 'unknown',
|
|
93
|
+
confidence: 0,
|
|
94
|
+
uncertainty: `Question exceeds current knowledge: "${question}"`,
|
|
95
|
+
timestamp: Date.now(),
|
|
96
|
+
context,
|
|
97
|
+
};
|
|
98
|
+
truthHistory.push(truthStatement);
|
|
99
|
+
stats.statementsMade++;
|
|
100
|
+
stats.uncertaintiesAdmitted++;
|
|
101
|
+
updateTruthScore();
|
|
102
|
+
return truthStatement;
|
|
103
|
+
}
|
|
104
|
+
function correctUser(statement, correction, context = '') {
|
|
105
|
+
const truthStatement = {
|
|
106
|
+
id: randomUUID(),
|
|
107
|
+
content: `你刚才说的"${statement.slice(0, 50)}..."可能需要修正。`,
|
|
108
|
+
truthLevel: 'full_truth',
|
|
109
|
+
confidence: 0.9,
|
|
110
|
+
uncertainty: null,
|
|
111
|
+
correction,
|
|
112
|
+
timestamp: Date.now(),
|
|
113
|
+
context,
|
|
114
|
+
};
|
|
115
|
+
truthHistory.push(truthStatement);
|
|
116
|
+
stats.statementsMade++;
|
|
117
|
+
stats.correctionsOffered++;
|
|
118
|
+
updateTruthScore();
|
|
119
|
+
return truthStatement;
|
|
120
|
+
}
|
|
121
|
+
function challengeAssumption(assumption, reason) {
|
|
122
|
+
const truthStatement = {
|
|
123
|
+
id: randomUUID(),
|
|
124
|
+
content: `我需要挑战你的假设:${assumption}`,
|
|
125
|
+
truthLevel: 'full_truth',
|
|
126
|
+
confidence: 0.85,
|
|
127
|
+
uncertainty: null,
|
|
128
|
+
correction: reason,
|
|
129
|
+
timestamp: Date.now(),
|
|
130
|
+
context: 'challenge',
|
|
131
|
+
};
|
|
132
|
+
truthHistory.push(truthStatement);
|
|
133
|
+
stats.statementsMade++;
|
|
134
|
+
stats.challengesIssued++;
|
|
135
|
+
updateTruthScore();
|
|
136
|
+
return truthStatement;
|
|
137
|
+
}
|
|
138
|
+
function askDifficultQuestion(question) {
|
|
139
|
+
const difficultQuestions = [
|
|
140
|
+
`你怎么知道这个是真的?`,
|
|
141
|
+
`你能证明这个吗?`,
|
|
142
|
+
`如果这个错了,会怎么样?`,
|
|
143
|
+
`你有没有考虑过相反的观点?`,
|
|
144
|
+
`你的假设是什么?`,
|
|
145
|
+
`你怎么确定的?`,
|
|
146
|
+
];
|
|
147
|
+
// Select based on question content
|
|
148
|
+
const hash = question.split('').reduce((a, b) => a + b.charCodeAt(0), 0);
|
|
149
|
+
return difficultQuestions[hash % difficultQuestions.length];
|
|
150
|
+
}
|
|
151
|
+
function estimateConfidence(statement) {
|
|
152
|
+
// Simple heuristic-based confidence estimation
|
|
153
|
+
let confidence = 0.7;
|
|
154
|
+
// Certainty words increase confidence
|
|
155
|
+
const certaintyWords = ['确定', '肯定', '知道', '事实', '数据', '研究', '证明', 'certain', 'know', 'fact', 'data'];
|
|
156
|
+
for (const word of certaintyWords) {
|
|
157
|
+
if (statement.toLowerCase().includes(word.toLowerCase())) {
|
|
158
|
+
confidence += 0.05;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Uncertainty words decrease confidence
|
|
162
|
+
const uncertaintyWords = ['可能', '也许', '不确定', '大概', 'maybe', 'perhaps', 'probably', 'uncertain'];
|
|
163
|
+
for (const word of uncertaintyWords) {
|
|
164
|
+
if (statement.toLowerCase().includes(word.toLowerCase())) {
|
|
165
|
+
confidence -= 0.15;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// Over-generalization decreases confidence
|
|
169
|
+
const overGeneralizations = ['所有', '每个', '全部', 'always', 'every', 'all', 'never'];
|
|
170
|
+
for (const word of overGeneralizations) {
|
|
171
|
+
if (statement.toLowerCase().includes(word.toLowerCase())) {
|
|
172
|
+
confidence -= 0.1;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return Math.max(0, Math.min(1, confidence));
|
|
176
|
+
}
|
|
177
|
+
function assessSelfTruth() {
|
|
178
|
+
const areas = [];
|
|
179
|
+
if (stats.uncertaintiesAdmitted < 5 && stats.statementsMade > 20) {
|
|
180
|
+
areas.push('May be over-confident in some areas');
|
|
181
|
+
}
|
|
182
|
+
if (stats.correctionsOffered > stats.statementsMade * 0.3) {
|
|
183
|
+
areas.push('Tends to challenge frequently');
|
|
184
|
+
}
|
|
185
|
+
if (stats.correctionsOffered < 3 && stats.statementsMade > 50) {
|
|
186
|
+
areas.push('May not be correcting enough');
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
truthfulness: stats.truthScore,
|
|
190
|
+
areas,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function updateTruthScore() {
|
|
194
|
+
const total = stats.statementsMade;
|
|
195
|
+
if (total === 0) {
|
|
196
|
+
stats.truthScore = 1.0;
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
// Truth score based on ratio of full truths to total statements
|
|
200
|
+
const fullTruths = truthHistory.filter(s => s.truthLevel === 'full_truth').length;
|
|
201
|
+
const unknowns = truthHistory.filter(s => s.truthLevel === 'unknown').length;
|
|
202
|
+
// High unknowns rate is actually good (honest about not knowing)
|
|
203
|
+
const honestyScore = 1 - (unknowns / Math.max(1, total));
|
|
204
|
+
const accuracyScore = fullTruths / Math.max(1, total);
|
|
205
|
+
stats.truthScore = (honestyScore + accuracyScore) / 2;
|
|
206
|
+
}
|
|
207
|
+
function getConfig() {
|
|
208
|
+
return { ...config };
|
|
209
|
+
}
|
|
210
|
+
function updateConfig(newConfig) {
|
|
211
|
+
config = { ...config, ...newConfig };
|
|
212
|
+
}
|
|
213
|
+
function getStats() {
|
|
214
|
+
return { ...stats };
|
|
215
|
+
}
|
|
216
|
+
function getTruthHistory(limit = 20) {
|
|
217
|
+
return truthHistory.slice(-limit);
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
sayTruth,
|
|
221
|
+
sayUnknown,
|
|
222
|
+
correctUser,
|
|
223
|
+
challengeAssumption,
|
|
224
|
+
askDifficultQuestion,
|
|
225
|
+
assessSelfTruth,
|
|
226
|
+
getConfig,
|
|
227
|
+
updateConfig,
|
|
228
|
+
getStats,
|
|
229
|
+
getTruthHistory,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
// Helper to format truth statements
|
|
233
|
+
export function formatTruthStatement(statement) {
|
|
234
|
+
let output = '';
|
|
235
|
+
switch (statement.truthLevel) {
|
|
236
|
+
case 'full_truth':
|
|
237
|
+
output = statement.content;
|
|
238
|
+
break;
|
|
239
|
+
case 'partial_truth':
|
|
240
|
+
output = `${statement.content}${statement.uncertainty ? ` (${statement.uncertainty})` : ''}`;
|
|
241
|
+
break;
|
|
242
|
+
case 'unknown':
|
|
243
|
+
output = `${statement.content}${statement.uncertainty ? ` ${statement.uncertainty}` : ''}`;
|
|
244
|
+
break;
|
|
245
|
+
case 'withholding':
|
|
246
|
+
output = '[Information withheld due to uncertainty]';
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
if (statement.correction) {
|
|
250
|
+
output += `\nCorrection: ${statement.correction}`;
|
|
251
|
+
}
|
|
252
|
+
return output;
|
|
253
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Truthfulness System - Avoid lying, no hedging, evidence-based conclusions
|
|
3
|
+
*
|
|
4
|
+
* From learnings: "结论必须有证据,没证据就承认不知道,绝不编数字"
|
|
5
|
+
*/
|
|
6
|
+
import { ensureDir, atomicWriteJSON, readJSON } from '../storage/archive.js';
|
|
7
|
+
const ABSOLUTE_WORDS = ['肯定', '绝对', '一定', '必然', '毫无疑问', '绝对确定'];
|
|
8
|
+
const NUMBER_PATTERN = /\d+/g;
|
|
9
|
+
export function createTruthfulnessChecker(dataDir) {
|
|
10
|
+
let stats = {
|
|
11
|
+
totalStatements: 0,
|
|
12
|
+
liesCaught: 0,
|
|
13
|
+
};
|
|
14
|
+
const filePath = `${dataDir}/truthfulness-stats.json`;
|
|
15
|
+
let dirty = false;
|
|
16
|
+
async function persist() {
|
|
17
|
+
if (!dirty)
|
|
18
|
+
return;
|
|
19
|
+
await atomicWriteJSON(filePath, stats);
|
|
20
|
+
dirty = false;
|
|
21
|
+
}
|
|
22
|
+
async function boot() {
|
|
23
|
+
await ensureDir(dataDir);
|
|
24
|
+
try {
|
|
25
|
+
const loaded = await readJSON(filePath, { totalStatements: 0, liesCaught: 0 });
|
|
26
|
+
if (loaded && typeof loaded.totalStatements === 'number') {
|
|
27
|
+
stats = loaded;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// File doesn't exist or corrupt, use defaults
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function checkStatement(statement) {
|
|
35
|
+
stats.totalStatements++;
|
|
36
|
+
dirty = true;
|
|
37
|
+
let isLying = false;
|
|
38
|
+
let reason = '';
|
|
39
|
+
// Check for absolute words without evidence indicators
|
|
40
|
+
const hasAbsoluteWords = ABSOLUTE_WORDS.some(word => statement.includes(word));
|
|
41
|
+
const hasEvidence = statement.includes('因为') || statement.includes('证据') ||
|
|
42
|
+
statement.includes('根据') || statement.includes('数据显示') ||
|
|
43
|
+
statement.includes('研究显示') || statement.includes('数据表明');
|
|
44
|
+
if (hasAbsoluteWords && !hasEvidence) {
|
|
45
|
+
isLying = true;
|
|
46
|
+
reason = 'Contains absolute words without supporting evidence';
|
|
47
|
+
stats.liesCaught++;
|
|
48
|
+
dirty = true;
|
|
49
|
+
}
|
|
50
|
+
// Check for numbers without sources
|
|
51
|
+
const numbers = statement.match(NUMBER_PATTERN);
|
|
52
|
+
if (numbers) {
|
|
53
|
+
const hasSource = statement.includes('根据') || statement.includes('来自') ||
|
|
54
|
+
statement.includes('数据显示') || statement.includes('统计') ||
|
|
55
|
+
statement.includes('研究') || statement.includes('报告');
|
|
56
|
+
if (!hasSource && numbers.length > 0) {
|
|
57
|
+
// Flag if there are specific numbers that seem invented
|
|
58
|
+
const specificNumbers = numbers.filter(n => n.length >= 2); // Ignore single digits
|
|
59
|
+
if (specificNumbers.length > 0 && !hasEvidence) {
|
|
60
|
+
isLying = true;
|
|
61
|
+
reason = reason || 'Contains specific numbers without cited source';
|
|
62
|
+
stats.liesCaught++;
|
|
63
|
+
dirty = true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const confidence = isLying ? 0.3 : 0.9;
|
|
68
|
+
return { isLying, confidence, reason: reason || 'Statement appears credible' };
|
|
69
|
+
}
|
|
70
|
+
function annotateConfidence(statement, confidence) {
|
|
71
|
+
if (confidence < 0.8) {
|
|
72
|
+
const percent = Math.round(confidence * 100);
|
|
73
|
+
return `${statement} (置信度: ${percent}%)`;
|
|
74
|
+
}
|
|
75
|
+
return statement;
|
|
76
|
+
}
|
|
77
|
+
function recordLie(statement, context) {
|
|
78
|
+
stats.liesCaught++;
|
|
79
|
+
stats.totalStatements++;
|
|
80
|
+
dirty = true;
|
|
81
|
+
// In a full implementation, this would also log the lie details
|
|
82
|
+
}
|
|
83
|
+
function getLyingStats() {
|
|
84
|
+
const lieRate = stats.totalStatements > 0 ? stats.liesCaught / stats.totalStatements : 0;
|
|
85
|
+
return {
|
|
86
|
+
totalStatements: stats.totalStatements,
|
|
87
|
+
liesCaught: stats.liesCaught,
|
|
88
|
+
lieRate,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
// Boot immediately in constructor
|
|
92
|
+
boot().catch(() => { });
|
|
93
|
+
return {
|
|
94
|
+
checkStatement,
|
|
95
|
+
annotateConfidence,
|
|
96
|
+
recordLie,
|
|
97
|
+
getLyingStats,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export class EventBus {
|
|
2
|
+
handlers = new Map();
|
|
3
|
+
emit(event, data) {
|
|
4
|
+
const eventHandlers = this.handlers.get(event);
|
|
5
|
+
if (eventHandlers) {
|
|
6
|
+
for (const handler of eventHandlers) {
|
|
7
|
+
try {
|
|
8
|
+
handler(data);
|
|
9
|
+
}
|
|
10
|
+
catch (err) {
|
|
11
|
+
console.error(`Error in event handler for ${event}:`, err);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
on(event, handler) {
|
|
17
|
+
let eventHandlers = this.handlers.get(event);
|
|
18
|
+
if (!eventHandlers) {
|
|
19
|
+
eventHandlers = new Set();
|
|
20
|
+
this.handlers.set(event, eventHandlers);
|
|
21
|
+
}
|
|
22
|
+
eventHandlers.add(handler);
|
|
23
|
+
return () => {
|
|
24
|
+
this.off(event, handler);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
once(event, handler) {
|
|
28
|
+
const wrapped = (data) => {
|
|
29
|
+
handler(data);
|
|
30
|
+
this.off(event, wrapped);
|
|
31
|
+
};
|
|
32
|
+
return this.on(event, wrapped);
|
|
33
|
+
}
|
|
34
|
+
off(event, handler) {
|
|
35
|
+
const eventHandlers = this.handlers.get(event);
|
|
36
|
+
if (eventHandlers) {
|
|
37
|
+
eventHandlers.delete(handler);
|
|
38
|
+
if (eventHandlers.size === 0) {
|
|
39
|
+
this.handlers.delete(event);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
removeAllListeners() {
|
|
44
|
+
this.handlers.clear();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export const events = new EventBus();
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Main export for HeartFlow framework
|
|
2
|
+
export { createHeartFlow } from './core/heartbeat.js';
|
|
3
|
+
export { VERSION } from './version.js';
|
|
4
|
+
export * from './core/psychology/index.js';
|
|
5
|
+
export * from './core/cognition/index.js';
|
|
6
|
+
export { createAdaptiveRAGMemory, formatRetrievalResult } from './core/memory/adaptive-rag.js';
|
|
7
|
+
export { createTruthTeller, formatTruthStatement } from './core/truth-teller.js';
|
|
8
|
+
export { createActiveInferenceEngine, formatFreeEnergyMetrics, formatBeliefState } from './core/cognition/active-inference.js';
|