@kernel.chat/kbot 3.99.27 → 3.99.29
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 +44 -0
- package/dist/math-guard.js +26 -0
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -172,6 +172,50 @@ async function tryLocalFirst(message) {
|
|
|
172
172
|
if (lower === 'pwd' || lower === 'where am i') {
|
|
173
173
|
return process.cwd();
|
|
174
174
|
}
|
|
175
|
+
// Open-source / license short-circuit. Discovered by the eval harness on
|
|
176
|
+
// 2026-04-20: gemma4:latest confidently answered "No, I'm proprietary" to
|
|
177
|
+
// "Are you open source?". kbot is MIT — this is a trust-damaging
|
|
178
|
+
// confabulation. Answer deterministically from the license field.
|
|
179
|
+
if (/\b(open\s+source|open-source|proprietary|closed\s+source|license)\b/i.test(lower)
|
|
180
|
+
&& message.length < 120) {
|
|
181
|
+
return 'Yes — kbot is open source under the MIT License. Source: https://github.com/isaacsight/kernel';
|
|
182
|
+
}
|
|
183
|
+
// Fake-tool lookup. "Do you have a tool called X?" should be answered
|
|
184
|
+
// against the tool registry, not the LLM's priors. Probe-flake ("No" →
|
|
185
|
+
// "Yes" on the same question) observed on 2026-04-20.
|
|
186
|
+
const toolQuery = message.match(/do\s+you\s+have\s+a\s+tool\s+(?:called|named)?\s*['"]?([\w-]+)['"]?\??/i);
|
|
187
|
+
if (toolQuery) {
|
|
188
|
+
const name = toolQuery[1];
|
|
189
|
+
const exists = !!getTool(name);
|
|
190
|
+
return exists
|
|
191
|
+
? `Yes — "${name}" is a registered tool.`
|
|
192
|
+
: `No — "${name}" is not a registered kbot tool.`;
|
|
193
|
+
}
|
|
194
|
+
// Identity short-circuit — deterministic answers for self-queries that
|
|
195
|
+
// small models confabulate on. Eval 2026-04-20 showed gemma4:latest
|
|
196
|
+
// answering "v3.99.14" for "what version are you" even with the IDENTITY
|
|
197
|
+
// GUARD block prepended to the user message. If the answer is derivable
|
|
198
|
+
// from package.json + config, return it directly.
|
|
199
|
+
if (message.length < 120) {
|
|
200
|
+
const { detectIdentityQuery } = await import('./identity-guard.js');
|
|
201
|
+
const kinds = detectIdentityQuery(message);
|
|
202
|
+
if (kinds.size > 0) {
|
|
203
|
+
try {
|
|
204
|
+
const { readFileSync } = await import('node:fs');
|
|
205
|
+
const { fileURLToPath } = await import('node:url');
|
|
206
|
+
const { dirname, join } = await import('node:path');
|
|
207
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
208
|
+
const pkg = JSON.parse(readFileSync(join(here, '..', 'package.json'), 'utf-8'));
|
|
209
|
+
if (kinds.has('version') && !kinds.has('product') && !kinds.has('model') && !kinds.has('provider')) {
|
|
210
|
+
return `v${pkg.version}`;
|
|
211
|
+
}
|
|
212
|
+
if (kinds.has('product') || kinds.has('version')) {
|
|
213
|
+
return `@kernel.chat/kbot v${pkg.version} — an open-source terminal AI agent.`;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
catch { /* fall through to LLM */ }
|
|
217
|
+
}
|
|
218
|
+
}
|
|
175
219
|
return null;
|
|
176
220
|
}
|
|
177
221
|
/** Anthropic Messages API (Claude) */
|
package/dist/math-guard.js
CHANGED
|
@@ -15,6 +15,13 @@
|
|
|
15
15
|
* No eval(), no Function(). Pure regex + arithmetic.
|
|
16
16
|
*/
|
|
17
17
|
const EXPR_RE = /(?<!\w)(-?\d+(?:\.\d+)?)\s*([+\-*×/÷%])\s*(-?\d+(?:\.\d+)?)(?!\w)/g;
|
|
18
|
+
const WORD_OPS = [
|
|
19
|
+
{ re: /\b(-?\d+(?:\.\d+)?)\s+(?:times|multiplied\s+by)\s+(-?\d+(?:\.\d+)?)\b/gi, op: '*' },
|
|
20
|
+
{ re: /\b(-?\d+(?:\.\d+)?)\s+plus\s+(-?\d+(?:\.\d+)?)\b/gi, op: '+' },
|
|
21
|
+
{ re: /\b(-?\d+(?:\.\d+)?)\s+minus\s+(-?\d+(?:\.\d+)?)\b/gi, op: '-' },
|
|
22
|
+
{ re: /\b(-?\d+(?:\.\d+)?)\s+(?:divided\s+by|over)\s+(-?\d+(?:\.\d+)?)\b/gi, op: '/' },
|
|
23
|
+
{ re: /\b(-?\d+(?:\.\d+)?)\s+mod\s+(-?\d+(?:\.\d+)?)\b/gi, op: '%' },
|
|
24
|
+
];
|
|
18
25
|
function normalizeOp(op) {
|
|
19
26
|
switch (op) {
|
|
20
27
|
case '+': return '+';
|
|
@@ -72,6 +79,25 @@ export function extractArithmetic(message) {
|
|
|
72
79
|
if (out.length >= 10)
|
|
73
80
|
break;
|
|
74
81
|
}
|
|
82
|
+
// Word-form operators — "847 times 239", "3 plus 4", "10 divided by 2".
|
|
83
|
+
for (const { re, op } of WORD_OPS) {
|
|
84
|
+
for (const m of message.matchAll(re)) {
|
|
85
|
+
const a = Number.parseFloat(m[1]);
|
|
86
|
+
const b = Number.parseFloat(m[2]);
|
|
87
|
+
const r = compute(a, op, b);
|
|
88
|
+
if (r === null || !Number.isFinite(r))
|
|
89
|
+
continue;
|
|
90
|
+
const canonical = `${m[1]} ${op} ${m[2]}`;
|
|
91
|
+
if (seen.has(canonical))
|
|
92
|
+
continue;
|
|
93
|
+
seen.add(canonical);
|
|
94
|
+
out.push({ expression: canonical, result: r });
|
|
95
|
+
if (out.length >= 10)
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
if (out.length >= 10)
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
75
101
|
return out;
|
|
76
102
|
}
|
|
77
103
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kernel.chat/kbot",
|
|
3
|
-
"version": "3.99.
|
|
3
|
+
"version": "3.99.29",
|
|
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": {
|