@kernel.chat/kbot 3.62.0 → 3.64.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/dist/agent.js +15 -1
- package/dist/buddy.d.ts +33 -0
- package/dist/buddy.js +468 -0
- package/dist/cli.js +75 -1
- package/dist/dream.d.ts +66 -0
- package/dist/dream.js +377 -0
- package/dist/memory-scanner.d.ts +60 -0
- package/dist/memory-scanner.js +461 -0
- package/dist/tools/buddy-tools.d.ts +2 -0
- package/dist/tools/buddy-tools.js +63 -0
- package/dist/tools/dream-tools.d.ts +2 -0
- package/dist/tools/dream-tools.js +159 -0
- package/dist/tools/index.js +4 -0
- package/dist/tools/memory-scanner-tools.d.ts +2 -0
- package/dist/tools/memory-scanner-tools.js +87 -0
- package/dist/tools/voice-input-tools.d.ts +2 -0
- package/dist/tools/voice-input-tools.js +132 -0
- package/dist/voice-input.d.ts +53 -0
- package/dist/voice-input.js +362 -0
- package/ollama-manifest.json +1 -1
- package/package.json +2 -2
package/dist/agent.js
CHANGED
|
@@ -16,6 +16,8 @@ import { formatContextForPrompt } from './context.js';
|
|
|
16
16
|
import { getMatrixSystemPrompt } from './matrix.js';
|
|
17
17
|
import { buildFullLearningContext, findPattern, recordPattern, cacheSolution, updateProfile, classifyTask, extractKeywords, learnFromExchange, updateProjectMemory, shouldAutoTrain, selfTrain, } from './learning.js';
|
|
18
18
|
import { getMemoryPrompt, addTurn, getPreviousMessages, getHistory } from './memory.js';
|
|
19
|
+
import { getDreamPrompt, dreamAfterSession } from './dream.js';
|
|
20
|
+
import { notifyTurn, startMemoryScanner, stopMemoryScanner } from './memory-scanner.js';
|
|
19
21
|
import { autoCompact, compressToolResult } from './context-manager.js';
|
|
20
22
|
import { learnedRoute, recordRoute } from './learned-router.js';
|
|
21
23
|
import { buildCacheablePrompt, createPromptSections } from './prompt-cache.js';
|
|
@@ -746,7 +748,9 @@ export async function runAgent(message, options = {}) {
|
|
|
746
748
|
const localResult = await tryLocalFirst(message);
|
|
747
749
|
if (localResult !== null) {
|
|
748
750
|
addTurn({ role: 'user', content: message }, memSession);
|
|
751
|
+
notifyTurn({ role: 'user', content: message }, memSession);
|
|
749
752
|
addTurn({ role: 'assistant', content: localResult }, memSession);
|
|
753
|
+
notifyTurn({ role: 'assistant', content: localResult }, memSession);
|
|
750
754
|
ui.onInfo('(handled locally — 0 tokens used)');
|
|
751
755
|
return { content: localResult, agent: 'local', model: 'none', toolCalls: 0 };
|
|
752
756
|
}
|
|
@@ -775,7 +779,9 @@ export async function runAgent(message, options = {}) {
|
|
|
775
779
|
}, { autoApprove: false, onApproval: async () => true });
|
|
776
780
|
const summary = formatPlanSummary(plan);
|
|
777
781
|
addTurn({ role: 'user', content: message }, memSession);
|
|
782
|
+
notifyTurn({ role: 'user', content: message }, memSession);
|
|
778
783
|
addTurn({ role: 'assistant', content: summary }, memSession);
|
|
784
|
+
notifyTurn({ role: 'assistant', content: summary }, memSession);
|
|
779
785
|
return {
|
|
780
786
|
content: summary,
|
|
781
787
|
agent: options.agent || 'coder',
|
|
@@ -965,7 +971,7 @@ Always quote file paths that contain spaces. Never reference internal system nam
|
|
|
965
971
|
persona: PERSONA,
|
|
966
972
|
matrixPrompt: matrixPrompt || undefined,
|
|
967
973
|
contextSnippet: (contextSnippet || '') + repoMapSnippet + graphSnippet + skillsSnippet + skillLibrarySnippet || undefined,
|
|
968
|
-
memorySnippet: (memorySnippet || '') + reflectionSnippet || undefined,
|
|
974
|
+
memorySnippet: (memorySnippet || '') + getDreamPrompt(8) + reflectionSnippet || undefined,
|
|
969
975
|
learningContext: ((learningContext || '') + (synthesisSnippet ? '\n\n' + synthesisSnippet : '') + (correctionsSnippet ? '\n\n' + correctionsSnippet : '')) || undefined,
|
|
970
976
|
});
|
|
971
977
|
const provider = byokProvider || 'anthropic';
|
|
@@ -997,6 +1003,8 @@ Always quote file paths that contain spaces. Never reference internal system nam
|
|
|
997
1003
|
model: options.model || 'auto',
|
|
998
1004
|
message: originalMessage.slice(0, 200),
|
|
999
1005
|
});
|
|
1006
|
+
// Start passive memory scanner for this session
|
|
1007
|
+
startMemoryScanner();
|
|
1000
1008
|
// ── Gödel limits: detect undecidable loops and hand off to human ──
|
|
1001
1009
|
const loopDetector = new LoopDetector({
|
|
1002
1010
|
maxToolRepeats: 5,
|
|
@@ -1292,7 +1300,9 @@ Always quote file paths that contain spaces. Never reference internal system nam
|
|
|
1292
1300
|
catch { /* self-eval errors are non-critical */ }
|
|
1293
1301
|
}
|
|
1294
1302
|
addTurn({ role: 'user', content: originalMessage }, memSession);
|
|
1303
|
+
notifyTurn({ role: 'user', content: originalMessage }, memSession);
|
|
1295
1304
|
addTurn({ role: 'assistant', content }, memSession);
|
|
1305
|
+
notifyTurn({ role: 'assistant', content }, memSession);
|
|
1296
1306
|
// ── Recursive Learning: record what worked (async — non-blocking) ──
|
|
1297
1307
|
const totalTokens = lastResponse.usage
|
|
1298
1308
|
? (lastResponse.usage.input_tokens || 0) + (lastResponse.usage.output_tokens || 0)
|
|
@@ -1603,6 +1613,10 @@ Always quote file paths that contain spaces. Never reference internal system nam
|
|
|
1603
1613
|
reason: 'loop_exhausted',
|
|
1604
1614
|
});
|
|
1605
1615
|
telemetry.destroy().catch(() => { });
|
|
1616
|
+
// ── Memory Scanner: stop and persist session stats ──
|
|
1617
|
+
stopMemoryScanner();
|
|
1618
|
+
// ── Dream Engine: consolidate session memories (non-blocking, $0 via Ollama) ──
|
|
1619
|
+
dreamAfterSession(sessionId);
|
|
1606
1620
|
const content = lastResponse?.content || 'Reached maximum tool iterations.';
|
|
1607
1621
|
return {
|
|
1608
1622
|
content,
|
package/dist/buddy.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type BuddySpecies = 'fox' | 'owl' | 'cat' | 'robot' | 'ghost' | 'mushroom' | 'octopus' | 'dragon';
|
|
2
|
+
export type BuddyMood = 'idle' | 'thinking' | 'success' | 'error' | 'learning';
|
|
3
|
+
export interface BuddyState {
|
|
4
|
+
species: BuddySpecies;
|
|
5
|
+
name: string;
|
|
6
|
+
mood: BuddyMood;
|
|
7
|
+
}
|
|
8
|
+
/** Get the buddy's current state (species, name, mood) */
|
|
9
|
+
export declare function getBuddy(): BuddyState;
|
|
10
|
+
/** Set the buddy's mood */
|
|
11
|
+
export declare function setBuddyMood(mood: BuddyMood): void;
|
|
12
|
+
/** Get the ASCII sprite for the buddy in the given mood (defaults to current) */
|
|
13
|
+
export declare function getBuddySprite(mood?: BuddyMood): string[];
|
|
14
|
+
/** Get a random greeting for the buddy */
|
|
15
|
+
export declare function getBuddyGreeting(): string;
|
|
16
|
+
/** Rename the buddy (persisted to ~/.kbot/buddy.json) */
|
|
17
|
+
export declare function renameBuddy(newName: string): void;
|
|
18
|
+
/**
|
|
19
|
+
* Format the buddy with a speech bubble and status message.
|
|
20
|
+
* Returns a multi-line string ready for terminal output.
|
|
21
|
+
*
|
|
22
|
+
* .----------------.
|
|
23
|
+
* | Status message |
|
|
24
|
+
* '----------------'
|
|
25
|
+
* /\ /\
|
|
26
|
+
* ( o . o )
|
|
27
|
+
* > ^ <
|
|
28
|
+
* /| |\
|
|
29
|
+
* (_| |_)
|
|
30
|
+
* ~ Patch the fox ~
|
|
31
|
+
*/
|
|
32
|
+
export declare function formatBuddyStatus(message?: string): string;
|
|
33
|
+
//# sourceMappingURL=buddy.d.ts.map
|
package/dist/buddy.js
ADDED
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
// kbot Buddy System — Terminal companion sprites
|
|
2
|
+
//
|
|
3
|
+
// Deterministic companion assignment based on config path hash.
|
|
4
|
+
// Same user always gets the same buddy. Mood changes based on session activity.
|
|
5
|
+
// Pure ASCII art, max 5 lines tall, 15 chars wide. Tamagotchi energy.
|
|
6
|
+
//
|
|
7
|
+
// Persists buddy name to ~/.kbot/buddy.json
|
|
8
|
+
import { homedir } from 'node:os';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
11
|
+
import { createHash } from 'node:crypto';
|
|
12
|
+
// ── Paths ──
|
|
13
|
+
const KBOT_DIR = join(homedir(), '.kbot');
|
|
14
|
+
const BUDDY_FILE = join(KBOT_DIR, 'buddy.json');
|
|
15
|
+
const CONFIG_PATH = join(KBOT_DIR, 'config.json');
|
|
16
|
+
// ── Species list (order matters — index = hash result) ──
|
|
17
|
+
const SPECIES = [
|
|
18
|
+
'fox', 'owl', 'cat', 'robot', 'ghost', 'mushroom', 'octopus', 'dragon',
|
|
19
|
+
];
|
|
20
|
+
// ── Default names per species ──
|
|
21
|
+
const DEFAULT_NAMES = {
|
|
22
|
+
fox: 'Patch',
|
|
23
|
+
owl: 'Hoot',
|
|
24
|
+
cat: 'Pixel',
|
|
25
|
+
robot: 'Bolt',
|
|
26
|
+
ghost: 'Wisp',
|
|
27
|
+
mushroom: 'Spore',
|
|
28
|
+
octopus: 'Ink',
|
|
29
|
+
dragon: 'Ember',
|
|
30
|
+
};
|
|
31
|
+
// ── ASCII Sprites ──
|
|
32
|
+
// Each sprite is an array of strings (lines). Max 5 lines, max 15 chars wide.
|
|
33
|
+
// Pure ASCII only — no unicode box drawing.
|
|
34
|
+
const SPRITES = {
|
|
35
|
+
fox: {
|
|
36
|
+
idle: [
|
|
37
|
+
' /\\ /\\ ',
|
|
38
|
+
' ( o . o ) ',
|
|
39
|
+
' > ^ < ',
|
|
40
|
+
' /| |\\ ',
|
|
41
|
+
'(_| |_) ',
|
|
42
|
+
],
|
|
43
|
+
thinking: [
|
|
44
|
+
' /\\ /\\ ',
|
|
45
|
+
' ( o . o ) ',
|
|
46
|
+
' > ~ < ..',
|
|
47
|
+
' /| |\\ ',
|
|
48
|
+
'(_| |_) ',
|
|
49
|
+
],
|
|
50
|
+
success: [
|
|
51
|
+
' /\\ /\\ ',
|
|
52
|
+
' ( ^ . ^ ) ',
|
|
53
|
+
' > w < ',
|
|
54
|
+
' \\| |/ ',
|
|
55
|
+
' | | ',
|
|
56
|
+
],
|
|
57
|
+
error: [
|
|
58
|
+
' /\\ /\\ ',
|
|
59
|
+
' ( ; . ; ) ',
|
|
60
|
+
' > n < ',
|
|
61
|
+
' /| |\\ ',
|
|
62
|
+
'(_| |_) ',
|
|
63
|
+
],
|
|
64
|
+
learning: [
|
|
65
|
+
' /\\ /\\ ',
|
|
66
|
+
' ( o . o ) ',
|
|
67
|
+
' > - < |] ',
|
|
68
|
+
' /| |\\ ',
|
|
69
|
+
'(_| |_) ',
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
owl: {
|
|
73
|
+
idle: [
|
|
74
|
+
' {o,o} ',
|
|
75
|
+
' /)__) ',
|
|
76
|
+
' -"--"-- ',
|
|
77
|
+
' | | ',
|
|
78
|
+
' ^ ^ ',
|
|
79
|
+
],
|
|
80
|
+
thinking: [
|
|
81
|
+
' {o,o} ',
|
|
82
|
+
' /)__)..',
|
|
83
|
+
' -"--"-- ',
|
|
84
|
+
' | | ',
|
|
85
|
+
' ^ ^ ',
|
|
86
|
+
],
|
|
87
|
+
success: [
|
|
88
|
+
' {^,^} ',
|
|
89
|
+
' /)__) ',
|
|
90
|
+
' -"--"-- ',
|
|
91
|
+
' \\| |/ ',
|
|
92
|
+
' ^ ^ ',
|
|
93
|
+
],
|
|
94
|
+
error: [
|
|
95
|
+
' {;,;} ',
|
|
96
|
+
' /)__) ',
|
|
97
|
+
' -"--"-- ',
|
|
98
|
+
' | | ',
|
|
99
|
+
' ^ ^ ',
|
|
100
|
+
],
|
|
101
|
+
learning: [
|
|
102
|
+
' {o,o} ',
|
|
103
|
+
' /)__)|]',
|
|
104
|
+
' -"--"-- ',
|
|
105
|
+
' | | ',
|
|
106
|
+
' ^ ^ ',
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
cat: {
|
|
110
|
+
idle: [
|
|
111
|
+
' /\\_/\\ ',
|
|
112
|
+
'( o.o ) ',
|
|
113
|
+
' > ^ < ',
|
|
114
|
+
' | | ',
|
|
115
|
+
' ~ ~ ',
|
|
116
|
+
],
|
|
117
|
+
thinking: [
|
|
118
|
+
' /\\_/\\ ',
|
|
119
|
+
'( o.o )..',
|
|
120
|
+
' > ^ < ',
|
|
121
|
+
' | | ',
|
|
122
|
+
' ~ ~ ',
|
|
123
|
+
],
|
|
124
|
+
success: [
|
|
125
|
+
' /\\_/\\ ',
|
|
126
|
+
'( ^.^ ) ',
|
|
127
|
+
' > w < ',
|
|
128
|
+
' \\ / ',
|
|
129
|
+
' ~ ~ ',
|
|
130
|
+
],
|
|
131
|
+
error: [
|
|
132
|
+
' /\\_/\\ ',
|
|
133
|
+
'( ;.; ) ',
|
|
134
|
+
' > n < ',
|
|
135
|
+
' | | ',
|
|
136
|
+
' ~ ~ ',
|
|
137
|
+
],
|
|
138
|
+
learning: [
|
|
139
|
+
' /\\_/\\ ',
|
|
140
|
+
'( o.o ) ',
|
|
141
|
+
' > - <|] ',
|
|
142
|
+
' | | ',
|
|
143
|
+
' ~ ~ ',
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
robot: {
|
|
147
|
+
idle: [
|
|
148
|
+
' [=====] ',
|
|
149
|
+
' |[o o]| ',
|
|
150
|
+
' | _ | ',
|
|
151
|
+
' |_____| ',
|
|
152
|
+
' || || ',
|
|
153
|
+
],
|
|
154
|
+
thinking: [
|
|
155
|
+
' [=====] ',
|
|
156
|
+
' |[o o]|.',
|
|
157
|
+
' | _ |.',
|
|
158
|
+
' |_____| ',
|
|
159
|
+
' || || ',
|
|
160
|
+
],
|
|
161
|
+
success: [
|
|
162
|
+
' [=====] ',
|
|
163
|
+
' |[^ ^]| ',
|
|
164
|
+
' | \\_/ | ',
|
|
165
|
+
' |_____| ',
|
|
166
|
+
' \\|| ||/ ',
|
|
167
|
+
],
|
|
168
|
+
error: [
|
|
169
|
+
' [=====] ',
|
|
170
|
+
' |[x x]| ',
|
|
171
|
+
' | ~ | ',
|
|
172
|
+
' |_____| ',
|
|
173
|
+
' || || ',
|
|
174
|
+
],
|
|
175
|
+
learning: [
|
|
176
|
+
' [=====] ',
|
|
177
|
+
' |[o o]| ',
|
|
178
|
+
' | _ | ',
|
|
179
|
+
' |_____|]',
|
|
180
|
+
' || || ',
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
ghost: {
|
|
184
|
+
idle: [
|
|
185
|
+
' .---. ',
|
|
186
|
+
' / o o \\ ',
|
|
187
|
+
'| o |',
|
|
188
|
+
' | | ',
|
|
189
|
+
' ~~W~~ ',
|
|
190
|
+
],
|
|
191
|
+
thinking: [
|
|
192
|
+
' .---. ',
|
|
193
|
+
' / o o \\..',
|
|
194
|
+
'| o |',
|
|
195
|
+
' | | ',
|
|
196
|
+
' ~~W~~ ',
|
|
197
|
+
],
|
|
198
|
+
success: [
|
|
199
|
+
' .---. ',
|
|
200
|
+
' / ^ ^ \\ ',
|
|
201
|
+
'| v |',
|
|
202
|
+
' | | ',
|
|
203
|
+
' ~~W~~ ',
|
|
204
|
+
],
|
|
205
|
+
error: [
|
|
206
|
+
' .---. ',
|
|
207
|
+
' / ; ; \\ ',
|
|
208
|
+
'| ~ |',
|
|
209
|
+
' | | ',
|
|
210
|
+
' ~~W~~ ',
|
|
211
|
+
],
|
|
212
|
+
learning: [
|
|
213
|
+
' .---. ',
|
|
214
|
+
' / o o \\ ',
|
|
215
|
+
'| o |]',
|
|
216
|
+
' | | ',
|
|
217
|
+
' ~~W~~ ',
|
|
218
|
+
],
|
|
219
|
+
},
|
|
220
|
+
mushroom: {
|
|
221
|
+
idle: [
|
|
222
|
+
' .-^-. ',
|
|
223
|
+
' / o o \\ ',
|
|
224
|
+
'|_______|',
|
|
225
|
+
' | | ',
|
|
226
|
+
' |_| ',
|
|
227
|
+
],
|
|
228
|
+
thinking: [
|
|
229
|
+
' .-^-. ',
|
|
230
|
+
' / o o \\..',
|
|
231
|
+
'|_______|',
|
|
232
|
+
' | | ',
|
|
233
|
+
' |_| ',
|
|
234
|
+
],
|
|
235
|
+
success: [
|
|
236
|
+
' .-^-. ',
|
|
237
|
+
' / ^ ^ \\ ',
|
|
238
|
+
'|_______|',
|
|
239
|
+
' \\| |/ ',
|
|
240
|
+
' |_| ',
|
|
241
|
+
],
|
|
242
|
+
error: [
|
|
243
|
+
' .-^-. ',
|
|
244
|
+
' / ; ; \\ ',
|
|
245
|
+
'|_______|',
|
|
246
|
+
' | | ',
|
|
247
|
+
' |_| ',
|
|
248
|
+
],
|
|
249
|
+
learning: [
|
|
250
|
+
' .-^-. ',
|
|
251
|
+
' / o o \\ ',
|
|
252
|
+
'|______|]',
|
|
253
|
+
' | | ',
|
|
254
|
+
' |_| ',
|
|
255
|
+
],
|
|
256
|
+
},
|
|
257
|
+
octopus: {
|
|
258
|
+
idle: [
|
|
259
|
+
' .---. ',
|
|
260
|
+
' / o o \\ ',
|
|
261
|
+
'| --- |',
|
|
262
|
+
' \\/\\/\\/\\/ ',
|
|
263
|
+
' ~ ~ ~ ',
|
|
264
|
+
],
|
|
265
|
+
thinking: [
|
|
266
|
+
' .---. ',
|
|
267
|
+
' / o o \\..',
|
|
268
|
+
'| --- |',
|
|
269
|
+
' \\/\\/\\/\\/ ',
|
|
270
|
+
' ~ ~ ~ ',
|
|
271
|
+
],
|
|
272
|
+
success: [
|
|
273
|
+
' .---. ',
|
|
274
|
+
' / ^ ^ \\ ',
|
|
275
|
+
'| \\_/ |',
|
|
276
|
+
' \\/\\/\\/\\/ ',
|
|
277
|
+
' \\~ ~ ~/ ',
|
|
278
|
+
],
|
|
279
|
+
error: [
|
|
280
|
+
' .---. ',
|
|
281
|
+
' / ; ; \\ ',
|
|
282
|
+
'| ~~~ |',
|
|
283
|
+
' \\/\\/\\/\\/ ',
|
|
284
|
+
' ~ ~ ~ ',
|
|
285
|
+
],
|
|
286
|
+
learning: [
|
|
287
|
+
' .---. ',
|
|
288
|
+
' / o o \\ ',
|
|
289
|
+
'| --- |]',
|
|
290
|
+
' \\/\\/\\/\\/ ',
|
|
291
|
+
' ~ ~ ~ ',
|
|
292
|
+
],
|
|
293
|
+
},
|
|
294
|
+
dragon: {
|
|
295
|
+
idle: [
|
|
296
|
+
' /\\_ ',
|
|
297
|
+
' / o > ',
|
|
298
|
+
'| --/\\ ',
|
|
299
|
+
' \\/\\/ ',
|
|
300
|
+
' ^^ ',
|
|
301
|
+
],
|
|
302
|
+
thinking: [
|
|
303
|
+
' /\\_ ',
|
|
304
|
+
' / o > ..',
|
|
305
|
+
'| --/\\ ',
|
|
306
|
+
' \\/\\/ ',
|
|
307
|
+
' ^^ ',
|
|
308
|
+
],
|
|
309
|
+
success: [
|
|
310
|
+
' /\\_ ',
|
|
311
|
+
' / ^ >* ',
|
|
312
|
+
'| --/\\ ',
|
|
313
|
+
' \\/\\/ ~ ',
|
|
314
|
+
' ^^ ',
|
|
315
|
+
],
|
|
316
|
+
error: [
|
|
317
|
+
' /\\_ ',
|
|
318
|
+
' / ; > ',
|
|
319
|
+
'| --/\\ ',
|
|
320
|
+
' \\/\\/ ',
|
|
321
|
+
' ^^ ',
|
|
322
|
+
],
|
|
323
|
+
learning: [
|
|
324
|
+
' /\\_ ',
|
|
325
|
+
' / o > ',
|
|
326
|
+
'| --/|] ',
|
|
327
|
+
' \\/\\/ ',
|
|
328
|
+
' ^^ ',
|
|
329
|
+
],
|
|
330
|
+
},
|
|
331
|
+
};
|
|
332
|
+
// ── Greetings per species ──
|
|
333
|
+
const GREETINGS = {
|
|
334
|
+
fox: ['Yip! Ready to dig in.', 'What are we hunting today?', 'Tail wagging. Lets go.'],
|
|
335
|
+
owl: ['Hoo! I see everything.', 'Wise choice opening kbot.', 'Night shift begins.'],
|
|
336
|
+
cat: ['Mrow. Fine, lets work.', 'I was napping, but ok.', 'Keyboard is warm. Go.'],
|
|
337
|
+
robot: ['Systems online.', 'All circuits nominal.', 'Beep boop. Ready.'],
|
|
338
|
+
ghost: ['Boo... I mean, hi!', 'Haunting your terminal.', 'Floating by to help.'],
|
|
339
|
+
mushroom: ['Sprouting up!', 'Growing ideas today.', 'Rooted and ready.'],
|
|
340
|
+
octopus: ['All arms on deck!', 'Eight ways to help.', 'Tentacles ready.'],
|
|
341
|
+
dragon: ['*tiny flame*', 'Wings stretched. Go.', 'Guarding your code.'],
|
|
342
|
+
};
|
|
343
|
+
// ── Mood messages ──
|
|
344
|
+
const MOOD_MESSAGES = {
|
|
345
|
+
idle: ['Just hanging out.', 'Waiting for action.', 'Idle but alert.'],
|
|
346
|
+
thinking: ['Hmm, thinking...', 'Processing...', 'Working on it...'],
|
|
347
|
+
success: ['Nailed it!', 'That worked!', 'Nice one!'],
|
|
348
|
+
error: ['Uh oh...', 'That stings.', 'Something broke.'],
|
|
349
|
+
learning: ['Studying patterns...', 'Learning something.', 'Getting smarter.'],
|
|
350
|
+
};
|
|
351
|
+
// ── State ──
|
|
352
|
+
let currentMood = 'idle';
|
|
353
|
+
let cachedSpecies = null;
|
|
354
|
+
let cachedName = null;
|
|
355
|
+
// ── Config persistence ──
|
|
356
|
+
function ensureDir() {
|
|
357
|
+
if (!existsSync(KBOT_DIR))
|
|
358
|
+
mkdirSync(KBOT_DIR, { recursive: true });
|
|
359
|
+
}
|
|
360
|
+
function loadBuddyConfig() {
|
|
361
|
+
if (!existsSync(BUDDY_FILE))
|
|
362
|
+
return {};
|
|
363
|
+
try {
|
|
364
|
+
return JSON.parse(readFileSync(BUDDY_FILE, 'utf-8'));
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
return {};
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
function saveBuddyConfig(config) {
|
|
371
|
+
ensureDir();
|
|
372
|
+
writeFileSync(BUDDY_FILE, JSON.stringify(config, null, 2));
|
|
373
|
+
}
|
|
374
|
+
// ── Species assignment (deterministic) ──
|
|
375
|
+
function hashConfigPath() {
|
|
376
|
+
const hash = createHash('sha256').update(CONFIG_PATH).digest();
|
|
377
|
+
// Use first 4 bytes as uint32, mod by species count
|
|
378
|
+
return hash.readUInt32BE(0) % SPECIES.length;
|
|
379
|
+
}
|
|
380
|
+
function resolveSpecies() {
|
|
381
|
+
if (cachedSpecies)
|
|
382
|
+
return cachedSpecies;
|
|
383
|
+
cachedSpecies = SPECIES[hashConfigPath()];
|
|
384
|
+
return cachedSpecies;
|
|
385
|
+
}
|
|
386
|
+
function resolveName() {
|
|
387
|
+
if (cachedName)
|
|
388
|
+
return cachedName;
|
|
389
|
+
const config = loadBuddyConfig();
|
|
390
|
+
cachedName = config.name || DEFAULT_NAMES[resolveSpecies()];
|
|
391
|
+
return cachedName;
|
|
392
|
+
}
|
|
393
|
+
// ── Public API ──
|
|
394
|
+
/** Get the buddy's current state (species, name, mood) */
|
|
395
|
+
export function getBuddy() {
|
|
396
|
+
return {
|
|
397
|
+
species: resolveSpecies(),
|
|
398
|
+
name: resolveName(),
|
|
399
|
+
mood: currentMood,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
/** Set the buddy's mood */
|
|
403
|
+
export function setBuddyMood(mood) {
|
|
404
|
+
currentMood = mood;
|
|
405
|
+
}
|
|
406
|
+
/** Get the ASCII sprite for the buddy in the given mood (defaults to current) */
|
|
407
|
+
export function getBuddySprite(mood) {
|
|
408
|
+
const m = mood ?? currentMood;
|
|
409
|
+
const species = resolveSpecies();
|
|
410
|
+
return SPRITES[species][m];
|
|
411
|
+
}
|
|
412
|
+
/** Get a random greeting for the buddy */
|
|
413
|
+
export function getBuddyGreeting() {
|
|
414
|
+
const species = resolveSpecies();
|
|
415
|
+
const greetings = GREETINGS[species];
|
|
416
|
+
const idx = Math.floor(Math.random() * greetings.length);
|
|
417
|
+
return greetings[idx];
|
|
418
|
+
}
|
|
419
|
+
/** Rename the buddy (persisted to ~/.kbot/buddy.json) */
|
|
420
|
+
export function renameBuddy(newName) {
|
|
421
|
+
const config = loadBuddyConfig();
|
|
422
|
+
config.name = newName.trim();
|
|
423
|
+
saveBuddyConfig(config);
|
|
424
|
+
cachedName = config.name;
|
|
425
|
+
}
|
|
426
|
+
/** Pick a random message for the current mood */
|
|
427
|
+
function moodMessage() {
|
|
428
|
+
const msgs = MOOD_MESSAGES[currentMood];
|
|
429
|
+
return msgs[Math.floor(Math.random() * msgs.length)];
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Format the buddy with a speech bubble and status message.
|
|
433
|
+
* Returns a multi-line string ready for terminal output.
|
|
434
|
+
*
|
|
435
|
+
* .----------------.
|
|
436
|
+
* | Status message |
|
|
437
|
+
* '----------------'
|
|
438
|
+
* /\ /\
|
|
439
|
+
* ( o . o )
|
|
440
|
+
* > ^ <
|
|
441
|
+
* /| |\
|
|
442
|
+
* (_| |_)
|
|
443
|
+
* ~ Patch the fox ~
|
|
444
|
+
*/
|
|
445
|
+
export function formatBuddyStatus(message) {
|
|
446
|
+
const name = resolveName();
|
|
447
|
+
const species = resolveSpecies();
|
|
448
|
+
const sprite = getBuddySprite();
|
|
449
|
+
const text = message || moodMessage();
|
|
450
|
+
// Build speech bubble
|
|
451
|
+
const inner = ` ${text} `;
|
|
452
|
+
const width = inner.length;
|
|
453
|
+
const top = '.' + '-'.repeat(width) + '.';
|
|
454
|
+
const mid = '|' + inner + '|';
|
|
455
|
+
const bot = "'" + '-'.repeat(width) + "'";
|
|
456
|
+
const lines = [];
|
|
457
|
+
lines.push(` ${top}`);
|
|
458
|
+
lines.push(` ${mid}`);
|
|
459
|
+
lines.push(` ${bot}`);
|
|
460
|
+
// Sprite lines
|
|
461
|
+
for (const line of sprite) {
|
|
462
|
+
lines.push(` ${line}`);
|
|
463
|
+
}
|
|
464
|
+
// Name tag
|
|
465
|
+
lines.push(` ~ ${name} the ${species} ~`);
|
|
466
|
+
return lines.join('\n');
|
|
467
|
+
}
|
|
468
|
+
//# sourceMappingURL=buddy.js.map
|
package/dist/cli.js
CHANGED
|
@@ -3158,6 +3158,80 @@ async function main() {
|
|
|
3158
3158
|
const r = await executeTool({ id: 'db_health', name: 'db_health', arguments: {} });
|
|
3159
3159
|
console.log(r.result);
|
|
3160
3160
|
});
|
|
3161
|
+
// ── Dream Engine ──
|
|
3162
|
+
const dreamCmd = program
|
|
3163
|
+
.command('dream')
|
|
3164
|
+
.description('Memory consolidation — consolidate session knowledge into durable insights');
|
|
3165
|
+
dreamCmd
|
|
3166
|
+
.command('run')
|
|
3167
|
+
.description('Run a dream cycle now (uses local Ollama)')
|
|
3168
|
+
.action(async () => {
|
|
3169
|
+
const { dream } = await import('./dream.js');
|
|
3170
|
+
printInfo('Dreaming... consolidating session memories with local AI');
|
|
3171
|
+
const result = await dream();
|
|
3172
|
+
if (result.success) {
|
|
3173
|
+
printSuccess(`Dream cycle #${result.cycle} complete`);
|
|
3174
|
+
console.log(` New insights: ${result.newInsights}`);
|
|
3175
|
+
console.log(` Reinforced: ${result.reinforced}`);
|
|
3176
|
+
console.log(` Archived: ${result.archived} aged-out`);
|
|
3177
|
+
console.log(` Duration: ${result.duration}ms`);
|
|
3178
|
+
}
|
|
3179
|
+
else {
|
|
3180
|
+
printWarn(result.error || 'Dream cycle failed');
|
|
3181
|
+
if (result.archived > 0)
|
|
3182
|
+
console.log(` (Still archived ${result.archived} aged-out insights)`);
|
|
3183
|
+
}
|
|
3184
|
+
});
|
|
3185
|
+
dreamCmd
|
|
3186
|
+
.command('status')
|
|
3187
|
+
.description('Show dream engine status and top insights')
|
|
3188
|
+
.action(async () => {
|
|
3189
|
+
const { getDreamStatus } = await import('./dream.js');
|
|
3190
|
+
const { state, insights, archiveCount } = getDreamStatus();
|
|
3191
|
+
console.log(chalk.bold('\nDream Engine'));
|
|
3192
|
+
console.log(chalk.dim('═══════════════════'));
|
|
3193
|
+
console.log(`Cycles: ${state.cycles}`);
|
|
3194
|
+
console.log(`Last: ${state.lastDream || 'never'}`);
|
|
3195
|
+
console.log(`Active: ${state.activeInsights} insights`);
|
|
3196
|
+
console.log(`Archived: ${state.totalArchived} (${archiveCount} files)`);
|
|
3197
|
+
if (insights.length > 0) {
|
|
3198
|
+
const avgRel = Math.round(insights.reduce((s, i) => s + i.relevance, 0) / insights.length * 100);
|
|
3199
|
+
console.log(`Avg relevance: ${avgRel}%`);
|
|
3200
|
+
console.log(chalk.bold('\nTop insights:'));
|
|
3201
|
+
for (const i of insights.slice(0, 8)) {
|
|
3202
|
+
const pct = Math.round(i.relevance * 100);
|
|
3203
|
+
console.log(` ${chalk.green(`${pct}%`)} [${chalk.cyan(i.category)}] ${i.content}`);
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
else {
|
|
3207
|
+
console.log(chalk.dim('\nNo insights yet. Run: kbot dream run'));
|
|
3208
|
+
}
|
|
3209
|
+
});
|
|
3210
|
+
dreamCmd
|
|
3211
|
+
.command('search <query>')
|
|
3212
|
+
.description('Search dream insights by keyword')
|
|
3213
|
+
.action(async (query) => {
|
|
3214
|
+
const { searchDreams } = await import('./dream.js');
|
|
3215
|
+
const results = searchDreams(query);
|
|
3216
|
+
if (results.length === 0) {
|
|
3217
|
+
printInfo(`No insights match "${query}"`);
|
|
3218
|
+
return;
|
|
3219
|
+
}
|
|
3220
|
+
console.log(chalk.bold(`\n${results.length} insights matching "${query}":\n`));
|
|
3221
|
+
for (const i of results.slice(0, 15)) {
|
|
3222
|
+
const pct = Math.round(i.relevance * 100);
|
|
3223
|
+
console.log(` ${chalk.green(`${pct}%`)} [${chalk.cyan(i.category)}] ${i.content}`);
|
|
3224
|
+
console.log(chalk.dim(` ${i.keywords.join(', ')} | ${i.sessions} sessions | ${i.created.split('T')[0]}`));
|
|
3225
|
+
}
|
|
3226
|
+
});
|
|
3227
|
+
dreamCmd
|
|
3228
|
+
.command('journal')
|
|
3229
|
+
.description('Print the full dream journal')
|
|
3230
|
+
.action(async () => {
|
|
3231
|
+
const { getDreamPrompt } = await import('./dream.js');
|
|
3232
|
+
const journal = getDreamPrompt(50);
|
|
3233
|
+
console.log(journal || chalk.dim('Dream journal is empty. Run: kbot dream run'));
|
|
3234
|
+
});
|
|
3161
3235
|
program.parse(process.argv);
|
|
3162
3236
|
const opts = program.opts();
|
|
3163
3237
|
const promptArgs = program.args;
|
|
@@ -3165,7 +3239,7 @@ async function main() {
|
|
|
3165
3239
|
if (opts.quiet)
|
|
3166
3240
|
setQuiet(true);
|
|
3167
3241
|
// If a sub-command was run, we're done
|
|
3168
|
-
if (['byok', 'auth', 'ide', 'local', 'ollama', 'kbot-local', 'pull', 'doctor', 'serve', 'agents', 'watch', 'voice', 'export', 'plugins', 'changelog', 'release', 'completions', 'automate', 'status', 'spec', 'a2a', 'init', 'email-agent', 'imessage-agent', 'consultation', 'observe', 'discovery', 'bench', 'lab', 'teach', 'sessions', 'admin', 'monitor', 'analytics', 'deploy', 'env', 'db'].includes(program.args[0]))
|
|
3242
|
+
if (['byok', 'auth', 'ide', 'local', 'ollama', 'kbot-local', 'pull', 'doctor', 'serve', 'agents', 'watch', 'voice', 'export', 'plugins', 'changelog', 'release', 'completions', 'automate', 'status', 'spec', 'a2a', 'init', 'email-agent', 'imessage-agent', 'consultation', 'observe', 'discovery', 'bench', 'lab', 'teach', 'sessions', 'admin', 'monitor', 'analytics', 'deploy', 'env', 'db', 'dream'].includes(program.args[0]))
|
|
3169
3243
|
return;
|
|
3170
3244
|
// ── Ollama Launch Integration ──
|
|
3171
3245
|
// Detect when kbot is started via `ollama launch kbot` or `kbot --ollama-launch`
|