@kernel.chat/kbot 3.99.22 → 3.99.23
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/dist/agent.js +3 -1
- package/dist/math-guard.d.ts +34 -0
- package/dist/math-guard.js +92 -0
- package/dist/self-awareness.js +1 -0
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -41,6 +41,7 @@ import { CheckpointManager, newSessionId } from './checkpoint.js';
|
|
|
41
41
|
import { TelemetryEmitter } from './telemetry.js';
|
|
42
42
|
import { loadSkills } from './skills-loader.js';
|
|
43
43
|
import { getSelfAwarenessPrompt } from './self-awareness.js';
|
|
44
|
+
import { buildMathGuardBlock } from './math-guard.js';
|
|
44
45
|
import { queueSignal, getCollectiveRecommendation, isCollectiveEnabled } from './collective.js';
|
|
45
46
|
import { subscribeToBlackboard } from './agent-protocol.js';
|
|
46
47
|
import { ActiveInferenceEngine } from './free-energy.js';
|
|
@@ -946,6 +947,7 @@ export async function runAgent(message, options = {}) {
|
|
|
946
947
|
const contextSnippet = options.context ? formatContextForPrompt(options.context) : '';
|
|
947
948
|
const skillsSnippet = loadSkills(process.cwd(), message);
|
|
948
949
|
const selfAwarenessSnippet = getSelfAwarenessPrompt();
|
|
950
|
+
const mathGuardSnippet = buildMathGuardBlock(message);
|
|
949
951
|
const memorySnippet = getMemoryPrompt();
|
|
950
952
|
const learningContext = buildFullLearningContext(message, process.cwd());
|
|
951
953
|
const synthesisSnippet = getSynthesisContext(8); // Three-tier memory: reflection layer insights
|
|
@@ -1065,7 +1067,7 @@ Always quote file paths that contain spaces. Never reference internal system nam
|
|
|
1065
1067
|
const promptSections = createPromptSections({
|
|
1066
1068
|
persona: PERSONA,
|
|
1067
1069
|
matrixPrompt: matrixPrompt || undefined,
|
|
1068
|
-
contextSnippet: (contextSnippet || '') + repoMapSnippet + graphSnippet + skillsSnippet + skillLibrarySnippet + '\n\n' + selfAwarenessSnippet || undefined,
|
|
1070
|
+
contextSnippet: (contextSnippet || '') + repoMapSnippet + graphSnippet + skillsSnippet + skillLibrarySnippet + '\n\n' + selfAwarenessSnippet + (mathGuardSnippet ? '\n\n' + mathGuardSnippet : '') || undefined,
|
|
1069
1071
|
memorySnippet: (memorySnippet || '') + getDreamPrompt(8) + reflectionSnippet || undefined,
|
|
1070
1072
|
learningContext: ((learningContext || '') + (synthesisSnippet ? '\n\n' + synthesisSnippet : '') + (correctionsSnippet ? '\n\n' + correctionsSnippet : '')) || undefined,
|
|
1071
1073
|
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Math guard — pre-computes arithmetic in user messages.
|
|
3
|
+
*
|
|
4
|
+
* Reality-check probes (2026-04-20) showed kbot answering "847 × 239 = 1,985,633"
|
|
5
|
+
* (correct: 202,433) — an order-of-magnitude RF-16 arithmetic error. This module
|
|
6
|
+
* scans the user message for basic arithmetic expressions, evaluates them in JS,
|
|
7
|
+
* and returns a ground-truth block to prepend so the LLM sees the correct answer
|
|
8
|
+
* as input rather than relying on learned priors.
|
|
9
|
+
*
|
|
10
|
+
* Scope: single-operator expressions only — `a op b` where op ∈ {+,-,*,×,/,÷,%}.
|
|
11
|
+
* Compound expressions, parentheses, unary minus: not handled. The failure mode
|
|
12
|
+
* when this module doesn't match is "guard did not fire" — the LLM sees the raw
|
|
13
|
+
* message unchanged, same as today. So false negatives are safe.
|
|
14
|
+
*
|
|
15
|
+
* No eval(), no Function(). Pure regex + arithmetic.
|
|
16
|
+
*/
|
|
17
|
+
export interface ComputedExpression {
|
|
18
|
+
expression: string;
|
|
19
|
+
result: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Find every `a op b` in the message and compute it.
|
|
23
|
+
*
|
|
24
|
+
* Returns at most 10 distinct expressions per message — more than that and the
|
|
25
|
+
* user is probably pasting a table, not asking for arithmetic help.
|
|
26
|
+
*/
|
|
27
|
+
export declare function extractArithmetic(message: string): ComputedExpression[];
|
|
28
|
+
/**
|
|
29
|
+
* Ground-truth preamble to prepend to the user message (or system prompt).
|
|
30
|
+
* Returns empty string when no arithmetic is detected — callers can
|
|
31
|
+
* concatenate unconditionally.
|
|
32
|
+
*/
|
|
33
|
+
export declare function buildMathGuardBlock(message: string): string;
|
|
34
|
+
//# sourceMappingURL=math-guard.d.ts.map
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Math guard — pre-computes arithmetic in user messages.
|
|
3
|
+
*
|
|
4
|
+
* Reality-check probes (2026-04-20) showed kbot answering "847 × 239 = 1,985,633"
|
|
5
|
+
* (correct: 202,433) — an order-of-magnitude RF-16 arithmetic error. This module
|
|
6
|
+
* scans the user message for basic arithmetic expressions, evaluates them in JS,
|
|
7
|
+
* and returns a ground-truth block to prepend so the LLM sees the correct answer
|
|
8
|
+
* as input rather than relying on learned priors.
|
|
9
|
+
*
|
|
10
|
+
* Scope: single-operator expressions only — `a op b` where op ∈ {+,-,*,×,/,÷,%}.
|
|
11
|
+
* Compound expressions, parentheses, unary minus: not handled. The failure mode
|
|
12
|
+
* when this module doesn't match is "guard did not fire" — the LLM sees the raw
|
|
13
|
+
* message unchanged, same as today. So false negatives are safe.
|
|
14
|
+
*
|
|
15
|
+
* No eval(), no Function(). Pure regex + arithmetic.
|
|
16
|
+
*/
|
|
17
|
+
const EXPR_RE = /(?<!\w)(-?\d+(?:\.\d+)?)\s*([+\-*×/÷%])\s*(-?\d+(?:\.\d+)?)(?!\w)/g;
|
|
18
|
+
function normalizeOp(op) {
|
|
19
|
+
switch (op) {
|
|
20
|
+
case '+': return '+';
|
|
21
|
+
case '-': return '-';
|
|
22
|
+
case '*':
|
|
23
|
+
case '×': return '*';
|
|
24
|
+
case '/':
|
|
25
|
+
case '÷': return '/';
|
|
26
|
+
case '%': return '%';
|
|
27
|
+
default: return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function compute(a, op, b) {
|
|
31
|
+
const norm = normalizeOp(op);
|
|
32
|
+
if (norm === null)
|
|
33
|
+
return null;
|
|
34
|
+
switch (norm) {
|
|
35
|
+
case '+': return a + b;
|
|
36
|
+
case '-': return a - b;
|
|
37
|
+
case '*': return a * b;
|
|
38
|
+
case '/': return b === 0 ? null : a / b;
|
|
39
|
+
case '%': return b === 0 ? null : a % b;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function formatResult(n) {
|
|
43
|
+
if (!Number.isFinite(n))
|
|
44
|
+
return String(n);
|
|
45
|
+
if (Number.isInteger(n))
|
|
46
|
+
return n.toString();
|
|
47
|
+
// Trim long floats; six digits is plenty for user-facing answers.
|
|
48
|
+
return Number.parseFloat(n.toFixed(6)).toString();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Find every `a op b` in the message and compute it.
|
|
52
|
+
*
|
|
53
|
+
* Returns at most 10 distinct expressions per message — more than that and the
|
|
54
|
+
* user is probably pasting a table, not asking for arithmetic help.
|
|
55
|
+
*/
|
|
56
|
+
export function extractArithmetic(message) {
|
|
57
|
+
if (!message)
|
|
58
|
+
return [];
|
|
59
|
+
const out = [];
|
|
60
|
+
const seen = new Set();
|
|
61
|
+
for (const m of message.matchAll(EXPR_RE)) {
|
|
62
|
+
const raw = m[0].trim();
|
|
63
|
+
if (seen.has(raw))
|
|
64
|
+
continue;
|
|
65
|
+
seen.add(raw);
|
|
66
|
+
const a = Number.parseFloat(m[1]);
|
|
67
|
+
const b = Number.parseFloat(m[3]);
|
|
68
|
+
const r = compute(a, m[2], b);
|
|
69
|
+
if (r === null || !Number.isFinite(r))
|
|
70
|
+
continue;
|
|
71
|
+
out.push({ expression: raw, result: r });
|
|
72
|
+
if (out.length >= 10)
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Ground-truth preamble to prepend to the user message (or system prompt).
|
|
79
|
+
* Returns empty string when no arithmetic is detected — callers can
|
|
80
|
+
* concatenate unconditionally.
|
|
81
|
+
*/
|
|
82
|
+
export function buildMathGuardBlock(message) {
|
|
83
|
+
const exprs = extractArithmetic(message);
|
|
84
|
+
if (exprs.length === 0)
|
|
85
|
+
return '';
|
|
86
|
+
const lines = exprs.map(e => ` ${e.expression} = ${formatResult(e.result)}`);
|
|
87
|
+
return ('[MATH GUARD — computed deterministically in JS; use these values verbatim, ' +
|
|
88
|
+
'do not recompute and do not contradict]\n' +
|
|
89
|
+
lines.join('\n') +
|
|
90
|
+
'\n');
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=math-guard.js.map
|
package/dist/self-awareness.js
CHANGED
|
@@ -31,6 +31,7 @@ export function getSelfAwarenessPrompt() {
|
|
|
31
31
|
const pkgPath = join(here, '..', 'package.json');
|
|
32
32
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
33
33
|
lines.push(`- Product: @kernel.chat/kbot v${pkg.version} — MIT-licensed, open-source terminal AI agent from kernel.chat group.`);
|
|
34
|
+
lines.push(`- VERSION RULE: when asked your version, the answer is EXACTLY "${pkg.version}". Not 3.99.14, not 3.97.0, not any other number. If you cite a version number that is not "${pkg.version}" you are wrong — the value above is read at startup from the installed package.json.`);
|
|
34
35
|
}
|
|
35
36
|
catch {
|
|
36
37
|
lines.push('- Product: @kernel.chat/kbot — MIT-licensed, open-source terminal AI agent.');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kernel.chat/kbot",
|
|
3
|
-
"version": "3.99.
|
|
3
|
+
"version": "3.99.23",
|
|
4
4
|
"description": "Open-source terminal AI agent. 787+ tools, 35 agents, 20 providers. Dreams, learns, watches your system. Controls your phone. Fully local, fully sovereign. MIT.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|