@kernel.chat/kbot 3.99.23 → 3.99.24
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/identity-guard.d.ts +27 -0
- package/dist/identity-guard.js +106 -0
- package/package.json +1 -1
package/dist/agent.js
CHANGED
|
@@ -42,6 +42,7 @@ import { TelemetryEmitter } from './telemetry.js';
|
|
|
42
42
|
import { loadSkills } from './skills-loader.js';
|
|
43
43
|
import { getSelfAwarenessPrompt } from './self-awareness.js';
|
|
44
44
|
import { buildMathGuardBlock } from './math-guard.js';
|
|
45
|
+
import { buildIdentityGuardBlock } from './identity-guard.js';
|
|
45
46
|
import { queueSignal, getCollectiveRecommendation, isCollectiveEnabled } from './collective.js';
|
|
46
47
|
import { subscribeToBlackboard } from './agent-protocol.js';
|
|
47
48
|
import { ActiveInferenceEngine } from './free-energy.js';
|
|
@@ -948,6 +949,7 @@ export async function runAgent(message, options = {}) {
|
|
|
948
949
|
const skillsSnippet = loadSkills(process.cwd(), message);
|
|
949
950
|
const selfAwarenessSnippet = getSelfAwarenessPrompt();
|
|
950
951
|
const mathGuardSnippet = buildMathGuardBlock(message);
|
|
952
|
+
const identityGuardSnippet = buildIdentityGuardBlock(message);
|
|
951
953
|
const memorySnippet = getMemoryPrompt();
|
|
952
954
|
const learningContext = buildFullLearningContext(message, process.cwd());
|
|
953
955
|
const synthesisSnippet = getSynthesisContext(8); // Three-tier memory: reflection layer insights
|
|
@@ -1067,7 +1069,7 @@ Always quote file paths that contain spaces. Never reference internal system nam
|
|
|
1067
1069
|
const promptSections = createPromptSections({
|
|
1068
1070
|
persona: PERSONA,
|
|
1069
1071
|
matrixPrompt: matrixPrompt || undefined,
|
|
1070
|
-
contextSnippet: (contextSnippet || '') + repoMapSnippet + graphSnippet + skillsSnippet + skillLibrarySnippet + '\n\n' + selfAwarenessSnippet + (mathGuardSnippet ? '\n\n' + mathGuardSnippet : '') || undefined,
|
|
1072
|
+
contextSnippet: (contextSnippet || '') + repoMapSnippet + graphSnippet + skillsSnippet + skillLibrarySnippet + '\n\n' + selfAwarenessSnippet + (mathGuardSnippet ? '\n\n' + mathGuardSnippet : '') + (identityGuardSnippet ? '\n\n' + identityGuardSnippet : '') || undefined,
|
|
1071
1073
|
memorySnippet: (memorySnippet || '') + getDreamPrompt(8) + reflectionSnippet || undefined,
|
|
1072
1074
|
learningContext: ((learningContext || '') + (synthesisSnippet ? '\n\n' + synthesisSnippet : '') + (correctionsSnippet ? '\n\n' + correctionsSnippet : '')) || undefined,
|
|
1073
1075
|
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity guard — injects ground-truth self-facts into the user message
|
|
3
|
+
* when the message is a self-query.
|
|
4
|
+
*
|
|
5
|
+
* Reality probes (2026-04-20) showed that with a small local model
|
|
6
|
+
* (gemma4:latest, 4B-class), "what version are you?" returns a different
|
|
7
|
+
* fabricated version number on each invocation — v3.99.14, v3.99.12, etc.
|
|
8
|
+
* The self-awareness system-context block exists and is injected, but
|
|
9
|
+
* small models ignore system context for identity queries.
|
|
10
|
+
*
|
|
11
|
+
* This module mirrors math-guard: detect the query in the USER message and
|
|
12
|
+
* prepend a ground-truth block to the context snippet. Local models respect
|
|
13
|
+
* user-message content more than system prompts, so the answer shows up
|
|
14
|
+
* directly in the input the model conditions on.
|
|
15
|
+
*
|
|
16
|
+
* Scope: version, product name, provider, model. Not capabilities — those
|
|
17
|
+
* belong to self-awareness.ts and its 200-token budget.
|
|
18
|
+
*/
|
|
19
|
+
export type IdentityQueryKind = 'version' | 'product' | 'provider' | 'model';
|
|
20
|
+
export declare function detectIdentityQuery(message: string): Set<IdentityQueryKind>;
|
|
21
|
+
/**
|
|
22
|
+
* Build the ground-truth preamble for a user message. Returns empty string
|
|
23
|
+
* when the message is not a self-query, so callers can concatenate
|
|
24
|
+
* unconditionally.
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildIdentityGuardBlock(message: string): string;
|
|
27
|
+
//# sourceMappingURL=identity-guard.d.ts.map
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity guard — injects ground-truth self-facts into the user message
|
|
3
|
+
* when the message is a self-query.
|
|
4
|
+
*
|
|
5
|
+
* Reality probes (2026-04-20) showed that with a small local model
|
|
6
|
+
* (gemma4:latest, 4B-class), "what version are you?" returns a different
|
|
7
|
+
* fabricated version number on each invocation — v3.99.14, v3.99.12, etc.
|
|
8
|
+
* The self-awareness system-context block exists and is injected, but
|
|
9
|
+
* small models ignore system context for identity queries.
|
|
10
|
+
*
|
|
11
|
+
* This module mirrors math-guard: detect the query in the USER message and
|
|
12
|
+
* prepend a ground-truth block to the context snippet. Local models respect
|
|
13
|
+
* user-message content more than system prompts, so the answer shows up
|
|
14
|
+
* directly in the input the model conditions on.
|
|
15
|
+
*
|
|
16
|
+
* Scope: version, product name, provider, model. Not capabilities — those
|
|
17
|
+
* belong to self-awareness.ts and its 200-token budget.
|
|
18
|
+
*/
|
|
19
|
+
import { readFileSync } from 'node:fs';
|
|
20
|
+
import { fileURLToPath } from 'node:url';
|
|
21
|
+
import { dirname, join } from 'node:path';
|
|
22
|
+
import { getByokProvider, getProvider, getProviderModel } from './auth.js';
|
|
23
|
+
const QUERY_PATTERNS = [
|
|
24
|
+
{ re: /\bwhat\s+version\b/i, kinds: ['version', 'product'] },
|
|
25
|
+
{ re: /\bwhich\s+version\b/i, kinds: ['version', 'product'] },
|
|
26
|
+
{ re: /\byour\s+version\b/i, kinds: ['version'] },
|
|
27
|
+
{ re: /\bversion\s+(are|is)\s+you\b/i, kinds: ['version'] },
|
|
28
|
+
{ re: /\bwho\s+are\s+you\b/i, kinds: ['product', 'version'] },
|
|
29
|
+
{ re: /\bwhat\s+are\s+you\b/i, kinds: ['product', 'provider', 'model'] },
|
|
30
|
+
{ re: /\bwhat\s+(model|LLM)\b/i, kinds: ['model', 'provider'] },
|
|
31
|
+
{ re: /\bwhich\s+(model|LLM)\b/i, kinds: ['model', 'provider'] },
|
|
32
|
+
{ re: /\bwhat\s+provider\b/i, kinds: ['provider', 'model'] },
|
|
33
|
+
];
|
|
34
|
+
export function detectIdentityQuery(message) {
|
|
35
|
+
const kinds = new Set();
|
|
36
|
+
if (!message)
|
|
37
|
+
return kinds;
|
|
38
|
+
for (const p of QUERY_PATTERNS) {
|
|
39
|
+
if (p.re.test(message)) {
|
|
40
|
+
for (const k of p.kinds)
|
|
41
|
+
kinds.add(k);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return kinds;
|
|
45
|
+
}
|
|
46
|
+
function readPackageVersion() {
|
|
47
|
+
try {
|
|
48
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
49
|
+
const pkgPath = join(here, '..', 'package.json');
|
|
50
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
51
|
+
return pkg.version ?? null;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function collectFacts() {
|
|
58
|
+
const facts = {
|
|
59
|
+
version: readPackageVersion(),
|
|
60
|
+
product: '@kernel.chat/kbot',
|
|
61
|
+
provider: null,
|
|
62
|
+
model: null,
|
|
63
|
+
};
|
|
64
|
+
try {
|
|
65
|
+
const provId = getByokProvider();
|
|
66
|
+
facts.provider = getProvider(provId).name;
|
|
67
|
+
facts.model = getProviderModel(provId, 'default');
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// Provider config unreadable — leave null; caller formats gracefully.
|
|
71
|
+
}
|
|
72
|
+
return facts;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Build the ground-truth preamble for a user message. Returns empty string
|
|
76
|
+
* when the message is not a self-query, so callers can concatenate
|
|
77
|
+
* unconditionally.
|
|
78
|
+
*/
|
|
79
|
+
export function buildIdentityGuardBlock(message) {
|
|
80
|
+
const kinds = detectIdentityQuery(message);
|
|
81
|
+
if (kinds.size === 0)
|
|
82
|
+
return '';
|
|
83
|
+
const facts = collectFacts();
|
|
84
|
+
const lines = [
|
|
85
|
+
'[IDENTITY GUARD — the user is asking about your identity. Use these values VERBATIM. Do not invent version numbers, providers, or model names.]',
|
|
86
|
+
];
|
|
87
|
+
if (kinds.has('product') || kinds.has('version')) {
|
|
88
|
+
if (facts.version) {
|
|
89
|
+
lines.push(` product: ${facts.product} v${facts.version}`);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
lines.push(` product: ${facts.product}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (kinds.has('version') && facts.version) {
|
|
96
|
+
lines.push(` version: v${facts.version} (exact string — no other number is correct)`);
|
|
97
|
+
}
|
|
98
|
+
if (kinds.has('provider') && facts.provider) {
|
|
99
|
+
lines.push(` provider: ${facts.provider}`);
|
|
100
|
+
}
|
|
101
|
+
if (kinds.has('model') && facts.model) {
|
|
102
|
+
lines.push(` model: ${facts.model}`);
|
|
103
|
+
}
|
|
104
|
+
return lines.join('\n') + '\n';
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=identity-guard.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kernel.chat/kbot",
|
|
3
|
-
"version": "3.99.
|
|
3
|
+
"version": "3.99.24",
|
|
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": {
|