@kernel.chat/kbot 3.64.0 → 3.66.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 +35 -6
- package/dist/agent.js +8 -0
- package/dist/cli.js +230 -31
- package/dist/collective-dreams.d.ts +36 -0
- package/dist/collective-dreams.js +182 -0
- package/dist/dream.d.ts +20 -1
- package/dist/dream.js +279 -10
- package/dist/learning.d.ts +6 -0
- package/dist/learning.js +41 -0
- package/dist/prompt-evolution.d.ts +9 -0
- package/dist/prompt-evolution.js +28 -0
- package/dist/tools/audit.d.ts +2 -1
- package/dist/tools/audit.js +127 -4
- package/dist/tools/collective-dream-tools.d.ts +2 -0
- package/dist/tools/collective-dream-tools.js +109 -0
- package/dist/tools/index.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
4
|
<strong>kbot</strong><br>
|
|
5
|
-
Open-source terminal AI agent. 35 agents.
|
|
5
|
+
Open-source terminal AI agent. 35 agents. 686+ tools. 20 providers. Science, finance, security, and more.
|
|
6
6
|
</p>
|
|
7
7
|
|
|
8
8
|
<p align="center">
|
|
@@ -30,17 +30,42 @@ Most terminal AI agents lock you into one provider, one model, one way of workin
|
|
|
30
30
|
- **Runs fully offline** — Embedded llama.cpp, Ollama, LM Studio, or Jan. $0, fully private.
|
|
31
31
|
- **Learns your patterns** — Bayesian skill ratings + pattern extraction. Gets faster over time.
|
|
32
32
|
- **35 specialist agents** — auto-routes your request to the right expert (coder, researcher, writer, guardian, quant, and 30 more).
|
|
33
|
-
- **
|
|
33
|
+
- **686+ tools** — files, bash, git, GitHub, web search, deploy, database, game dev, VFX, research, science, finance, security, and more.
|
|
34
34
|
- **Programmatic SDK** — use kbot as a library in your own apps.
|
|
35
35
|
- **MCP server built in** — plug kbot into Claude Code, Cursor, VS Code, Zed, or Neovim as a tool provider.
|
|
36
36
|
|
|
37
|
+
## Highlights
|
|
38
|
+
|
|
39
|
+
### Dream Engine — Your AI Remembers You
|
|
40
|
+
|
|
41
|
+
After each session, kbot "dreams" — consolidating what it learned about you into durable insights using local Ollama models. $0 cost. Insights feed back into future sessions automatically.
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
kbot dream run # Trigger consolidation
|
|
45
|
+
kbot dream status # See what kbot learned
|
|
46
|
+
kbot dream journal # Full insight history
|
|
47
|
+
kbot dream search # Find specific memories
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
5-tier memory: pattern cache -> solution index -> user profile -> dream journal -> passive scanner. All tiers feed each other through the dream engine.
|
|
51
|
+
|
|
52
|
+
### Audit Any Repo in One Command
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
kbot audit facebook/react
|
|
56
|
+
kbot audit --share vercel/next.js # Creates a public Gist
|
|
57
|
+
kbot audit --badge your/repo # Badge for your README
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Checks security, documentation, code quality, CI/CD, community health, and DevOps. Scored out of 100, graded A-F. Add the badge to your README.
|
|
61
|
+
|
|
37
62
|
### How it compares
|
|
38
63
|
|
|
39
64
|
| | kbot | Claude Code | Codex CLI | Aider | OpenCode |
|
|
40
65
|
|---|---|---|---|---|---|
|
|
41
66
|
| AI providers | 20 | 1 | 1 | 6 | 75+ |
|
|
42
67
|
| Specialist agents | 35 | 0 | 0 | 0 | 0 |
|
|
43
|
-
| Built-in tools |
|
|
68
|
+
| Built-in tools | 686+ | ~20 | ~15 | ~10 | ~15 |
|
|
44
69
|
| Science tools | 114 | 0 | 0 | 0 | 0 |
|
|
45
70
|
| Learning engine | Yes | No | No | No | No |
|
|
46
71
|
| Offline mode | Embedded + Ollama | No | No | Ollama | Ollama |
|
|
@@ -93,7 +118,7 @@ kbot auto-routes to the right agent for each task. Or pick one with `--agent <na
|
|
|
93
118
|
| **Domain** | infrastructure, quant, investigator, oracle, chronist, sage, communicator, adapter |
|
|
94
119
|
| **Presets** | claude-code, cursor, copilot, creative, developer |
|
|
95
120
|
|
|
96
|
-
##
|
|
121
|
+
## 686+ Tools
|
|
97
122
|
|
|
98
123
|
| Category | Examples |
|
|
99
124
|
|----------|---------|
|
|
@@ -185,7 +210,7 @@ graph TD
|
|
|
185
210
|
D -->|Multi-step| F[Autonomous Planner]
|
|
186
211
|
E --> G[Provider API + Tool Loop]
|
|
187
212
|
F --> G
|
|
188
|
-
G --> H{
|
|
213
|
+
G --> H{686+ Tools}
|
|
189
214
|
H --> I[File ops, bash, git, GitHub, search, deploy, DB, game dev...]
|
|
190
215
|
G --> J[Learning Engine]
|
|
191
216
|
J --> K[Patterns + Solutions + User Profile]
|
|
@@ -218,7 +243,11 @@ Works with Claude Code, Cursor, VS Code, Windsurf, Zed, Neovim.
|
|
|
218
243
|
| `kbot auth` | Configure API key |
|
|
219
244
|
| `kbot local` | Use local AI (Ollama, embedded, LM Studio, Jan) |
|
|
220
245
|
| `kbot serve` | Start HTTP REST + SSE streaming server |
|
|
221
|
-
| `kbot audit <repo>` | Security + quality audit of any GitHub repo |
|
|
246
|
+
| `kbot audit <repo>` | Security + quality audit of any GitHub repo (A-F grade) |
|
|
247
|
+
| `kbot dream run` | Consolidate session learnings into durable insights |
|
|
248
|
+
| `kbot dream status` | See what kbot has learned about you |
|
|
249
|
+
| `kbot dream journal` | Full insight history |
|
|
250
|
+
| `kbot dream search` | Find specific memories |
|
|
222
251
|
| `kbot contribute <repo>` | Find good-first-issues and quick wins |
|
|
223
252
|
| `kbot share` | Share conversation as GitHub Gist |
|
|
224
253
|
| `kbot pair` | File watcher with auto-analysis |
|
package/dist/agent.js
CHANGED
|
@@ -17,6 +17,7 @@ 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
19
|
import { getDreamPrompt, dreamAfterSession } from './dream.js';
|
|
20
|
+
import { setBuddyMood } from './buddy.js';
|
|
20
21
|
import { notifyTurn, startMemoryScanner, stopMemoryScanner } from './memory-scanner.js';
|
|
21
22
|
import { autoCompact, compressToolResult } from './context-manager.js';
|
|
22
23
|
import { learnedRoute, recordRoute } from './learned-router.js';
|
|
@@ -1003,6 +1004,7 @@ Always quote file paths that contain spaces. Never reference internal system nam
|
|
|
1003
1004
|
model: options.model || 'auto',
|
|
1004
1005
|
message: originalMessage.slice(0, 200),
|
|
1005
1006
|
});
|
|
1007
|
+
setBuddyMood('thinking');
|
|
1006
1008
|
// Start passive memory scanner for this session
|
|
1007
1009
|
startMemoryScanner();
|
|
1008
1010
|
// ── Gödel limits: detect undecidable loops and hand off to human ──
|
|
@@ -1531,6 +1533,8 @@ Always quote file paths that contain spaces. Never reference internal system nam
|
|
|
1531
1533
|
};
|
|
1532
1534
|
results.push(result);
|
|
1533
1535
|
ui.onToolCallEnd(call.name, result.result, result.error ? result.result : undefined, result.duration_ms);
|
|
1536
|
+
// Update buddy mood based on tool outcome
|
|
1537
|
+
setBuddyMood(result.error ? 'error' : 'success');
|
|
1534
1538
|
// ── Observer: record tool call for cross-session learning ──
|
|
1535
1539
|
try {
|
|
1536
1540
|
const { recordObservation } = await import('./observer.js');
|
|
@@ -1598,6 +1602,7 @@ Always quote file paths that contain spaces. Never reference internal system nam
|
|
|
1598
1602
|
}
|
|
1599
1603
|
catch (err) {
|
|
1600
1604
|
spinnerHandle?.stop();
|
|
1605
|
+
setBuddyMood('error');
|
|
1601
1606
|
// ── Telemetry: session failure ──
|
|
1602
1607
|
telemetry.emit('session_end', { status: 'failed', error: String(err), toolCallCount });
|
|
1603
1608
|
telemetry.destroy().catch(() => { });
|
|
@@ -1616,7 +1621,10 @@ Always quote file paths that contain spaces. Never reference internal system nam
|
|
|
1616
1621
|
// ── Memory Scanner: stop and persist session stats ──
|
|
1617
1622
|
stopMemoryScanner();
|
|
1618
1623
|
// ── Dream Engine: consolidate session memories (non-blocking, $0 via Ollama) ──
|
|
1624
|
+
setBuddyMood('learning');
|
|
1619
1625
|
dreamAfterSession(sessionId);
|
|
1626
|
+
// Session complete — buddy returns to idle
|
|
1627
|
+
setBuddyMood('idle');
|
|
1620
1628
|
const content = lastResponse?.content || 'Reached maximum tool iterations.';
|
|
1621
1629
|
return {
|
|
1622
1630
|
content,
|
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { createInterface } from 'node:readline';
|
|
12
12
|
import { existsSync } from 'node:fs';
|
|
13
13
|
import { join, basename } from 'node:path';
|
|
14
|
+
import { homedir } from 'node:os';
|
|
14
15
|
import { Command } from 'commander';
|
|
15
16
|
import { loadConfig, setupByok, setupEmbedded, isByokEnabled, isLocalProvider, disableByok, detectProvider, getByokProvider, PROVIDERS, setupOllama, setupKbotLocal, isOllamaRunning, listOllamaModels, warmOllamaModelCache } from './auth.js';
|
|
16
17
|
import { runAndPrint, runAgent, runAgentFromCheckpoint } from './agent.js';
|
|
@@ -26,6 +27,7 @@ import { banner, bannerCompact, bannerAuth, prompt as kbotPrompt, printError, pr
|
|
|
26
27
|
import { checkForUpdate, selfUpdate } from './updater.js';
|
|
27
28
|
import { runTutorial } from './tutorial.js';
|
|
28
29
|
import { syncOnStartup, schedulePush, flushCloudSync, isCloudSyncEnabled, setCloudToken, getCloudToken } from './cloud-sync.js';
|
|
30
|
+
import { getBuddy, getBuddyGreeting, formatBuddyStatus } from './buddy.js';
|
|
29
31
|
import chalk from 'chalk';
|
|
30
32
|
import { createRequire } from 'node:module';
|
|
31
33
|
const __require = createRequire(import.meta.url);
|
|
@@ -2439,7 +2441,7 @@ async function main() {
|
|
|
2439
2441
|
.option('--json', 'Output raw JSON')
|
|
2440
2442
|
.option('--badge', 'Print only the badge markdown (for adding to READMEs)')
|
|
2441
2443
|
.action(async (repo, auditOpts) => {
|
|
2442
|
-
const { auditRepo, formatAuditReport } = await import('./tools/audit.js');
|
|
2444
|
+
const { auditRepo, formatAuditReport, formatAuditTerminal } = await import('./tools/audit.js');
|
|
2443
2445
|
printInfo(`Auditing ${repo}...`);
|
|
2444
2446
|
try {
|
|
2445
2447
|
const result = await auditRepo(repo);
|
|
@@ -2453,14 +2455,16 @@ async function main() {
|
|
|
2453
2455
|
console.log(`[-${badgeColor})](https://www.npmjs.com/package/@kernel.chat/kbot)`);
|
|
2454
2456
|
return;
|
|
2455
2457
|
}
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2458
|
+
// Terminal gets the styled version; --share gist gets markdown
|
|
2459
|
+
const terminalReport = formatAuditTerminal(result);
|
|
2460
|
+
console.log(terminalReport);
|
|
2461
|
+
// Auto-share as gist (uses markdown format for portability)
|
|
2459
2462
|
if (auditOpts.share) {
|
|
2460
2463
|
printInfo('Sharing audit report...');
|
|
2461
2464
|
try {
|
|
2465
|
+
const markdownReport = formatAuditReport(result);
|
|
2462
2466
|
const { createGist } = await import('./share.js');
|
|
2463
|
-
const url = createGist(
|
|
2467
|
+
const url = createGist(markdownReport, `kbot-audit-${repo.replace('/', '-')}.md`, `kbot Audit: ${repo} — Grade ${result.grade}`, true);
|
|
2464
2468
|
if (url?.startsWith('http')) {
|
|
2465
2469
|
printSuccess(`Shared! ${url}`);
|
|
2466
2470
|
printInfo(`Badge for ${repo}'s README:`);
|
|
@@ -3167,20 +3171,28 @@ async function main() {
|
|
|
3167
3171
|
.description('Run a dream cycle now (uses local Ollama)')
|
|
3168
3172
|
.action(async () => {
|
|
3169
3173
|
const { dream } = await import('./dream.js');
|
|
3170
|
-
|
|
3174
|
+
console.log();
|
|
3175
|
+
console.log(` ${chalk.hex('#A78BFA')('◆')} ${chalk.bold('Dream Engine')} ${chalk.dim('consolidating memories...')}`);
|
|
3176
|
+
console.log();
|
|
3171
3177
|
const result = await dream();
|
|
3172
3178
|
if (result.success) {
|
|
3173
|
-
|
|
3174
|
-
console.log(
|
|
3175
|
-
console.log(`
|
|
3176
|
-
console.log(`
|
|
3177
|
-
|
|
3179
|
+
console.log(` ${chalk.hex('#4ADE80')('✓')} ${chalk.bold(`Cycle #${result.cycle} complete`)} ${chalk.dim(`${result.duration}ms`)}`);
|
|
3180
|
+
console.log();
|
|
3181
|
+
console.log(` ${chalk.hex('#4ADE80')('+')} ${chalk.bold(String(result.newInsights))} new insights`);
|
|
3182
|
+
console.log(` ${chalk.hex('#A78BFA')('↻')} ${chalk.bold(String(result.reinforced))} reinforced`);
|
|
3183
|
+
if (result.archived > 0) {
|
|
3184
|
+
console.log(` ${chalk.dim('↓')} ${chalk.dim(`${result.archived} archived (aged out)`)}`);
|
|
3185
|
+
}
|
|
3186
|
+
console.log();
|
|
3187
|
+
console.log(` ${chalk.dim('View results:')} ${chalk.hex('#A78BFA')('kbot dream status')}`);
|
|
3178
3188
|
}
|
|
3179
3189
|
else {
|
|
3180
|
-
|
|
3181
|
-
if (result.archived > 0)
|
|
3182
|
-
console.log(`
|
|
3190
|
+
console.log(` ${chalk.hex('#FBBF24')('!')} ${result.error || 'Dream cycle failed'}`);
|
|
3191
|
+
if (result.archived > 0) {
|
|
3192
|
+
console.log(` ${chalk.dim('↓')} ${chalk.dim(`${result.archived} insights archived (aging only)`)}`);
|
|
3193
|
+
}
|
|
3183
3194
|
}
|
|
3195
|
+
console.log();
|
|
3184
3196
|
});
|
|
3185
3197
|
dreamCmd
|
|
3186
3198
|
.command('status')
|
|
@@ -3188,23 +3200,86 @@ async function main() {
|
|
|
3188
3200
|
.action(async () => {
|
|
3189
3201
|
const { getDreamStatus } = await import('./dream.js');
|
|
3190
3202
|
const { state, insights, archiveCount } = getDreamStatus();
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3203
|
+
// ── Helper functions ──
|
|
3204
|
+
const W = 56; // inner width
|
|
3205
|
+
const box = {
|
|
3206
|
+
tl: '╭', tr: '╮', bl: '╰', br: '╯', h: '─', v: '│',
|
|
3207
|
+
pad: (s, w) => {
|
|
3208
|
+
// Pad string to width, accounting for chalk ANSI codes
|
|
3209
|
+
const visible = s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
3210
|
+
const diff = w - visible.length;
|
|
3211
|
+
return diff > 0 ? s + ' '.repeat(diff) : s;
|
|
3212
|
+
},
|
|
3213
|
+
};
|
|
3214
|
+
const relevanceBar = (pct, len = 20) => {
|
|
3215
|
+
const filled = Math.round((pct / 100) * len);
|
|
3216
|
+
const empty = len - filled;
|
|
3217
|
+
const color = pct >= 70 ? chalk.hex('#4ADE80') : pct >= 40 ? chalk.hex('#FBBF24') : chalk.hex('#F87171');
|
|
3218
|
+
return color('█'.repeat(filled)) + chalk.dim('░'.repeat(empty));
|
|
3219
|
+
};
|
|
3220
|
+
const categoryColor = (cat) => {
|
|
3221
|
+
const colors = {
|
|
3222
|
+
pattern: '#A78BFA', preference: '#67E8F9', skill: '#4ADE80',
|
|
3223
|
+
project: '#FB923C', relationship: '#F472B6',
|
|
3224
|
+
};
|
|
3225
|
+
return chalk.hex(colors[cat] || '#A78BFA');
|
|
3226
|
+
};
|
|
3227
|
+
const categoryChip = (cat) => {
|
|
3228
|
+
const c = categoryColor(cat);
|
|
3229
|
+
return c(` ${cat.toUpperCase()} `);
|
|
3230
|
+
};
|
|
3231
|
+
// ── Header box ──
|
|
3232
|
+
console.log();
|
|
3233
|
+
console.log(chalk.hex('#A78BFA')(` ${box.tl}${box.h.repeat(W)}${box.tr}`));
|
|
3234
|
+
console.log(chalk.hex('#A78BFA')(` ${box.v}`) + box.pad(` ${chalk.hex('#A78BFA').bold('◆ DREAM ENGINE')} ${chalk.dim('memory consolidation')}`, W) + chalk.hex('#A78BFA')(box.v));
|
|
3235
|
+
console.log(chalk.hex('#A78BFA')(` ${box.bl}${box.h.repeat(W)}${box.br}`));
|
|
3236
|
+
console.log();
|
|
3237
|
+
// ── Stats row ──
|
|
3238
|
+
const lastDreamDisplay = state.lastDream
|
|
3239
|
+
? new Date(state.lastDream).toLocaleDateString('en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })
|
|
3240
|
+
: chalk.dim('never');
|
|
3241
|
+
console.log(` ${chalk.bold('Cycles')} ${chalk.hex('#A78BFA')(String(state.cycles))} ${chalk.bold('Last')} ${lastDreamDisplay} ${chalk.bold('Active')} ${chalk.hex('#4ADE80')(String(state.activeInsights))}`);
|
|
3242
|
+
console.log(` ${chalk.bold('Total')} ${chalk.dim(String(state.totalInsights))} ${chalk.bold('Archived')} ${chalk.dim(`${state.totalArchived} (${archiveCount} files)`)}`);
|
|
3243
|
+
console.log();
|
|
3197
3244
|
if (insights.length > 0) {
|
|
3245
|
+
// ── Average relevance bar ──
|
|
3198
3246
|
const avgRel = Math.round(insights.reduce((s, i) => s + i.relevance, 0) / insights.length * 100);
|
|
3199
|
-
console.log(`Avg
|
|
3200
|
-
console.log(
|
|
3247
|
+
console.log(` ${chalk.bold('Avg Relevance')} ${relevanceBar(avgRel, 24)} ${chalk.bold(`${avgRel}%`)}`);
|
|
3248
|
+
console.log();
|
|
3249
|
+
// ── Category breakdown ──
|
|
3250
|
+
const catCounts = {};
|
|
3251
|
+
for (const i of insights)
|
|
3252
|
+
catCounts[i.category] = (catCounts[i.category] || 0) + 1;
|
|
3253
|
+
const chips = Object.entries(catCounts)
|
|
3254
|
+
.sort((a, b) => b[1] - a[1])
|
|
3255
|
+
.map(([cat, count]) => `${categoryChip(cat)} ${chalk.dim(`${count}`)}`)
|
|
3256
|
+
.join(' ');
|
|
3257
|
+
console.log(` ${chalk.bold('Categories')} ${chips}`);
|
|
3258
|
+
console.log();
|
|
3259
|
+
// ── Divider ──
|
|
3260
|
+
console.log(chalk.dim(` ${'─'.repeat(W)}`));
|
|
3261
|
+
console.log();
|
|
3262
|
+
// ── Top insights ──
|
|
3263
|
+
console.log(` ${chalk.bold('Top Insights')}`);
|
|
3264
|
+
console.log();
|
|
3201
3265
|
for (const i of insights.slice(0, 8)) {
|
|
3202
3266
|
const pct = Math.round(i.relevance * 100);
|
|
3203
|
-
|
|
3267
|
+
const bar = relevanceBar(pct, 12);
|
|
3268
|
+
const tag = categoryChip(i.category);
|
|
3269
|
+
console.log(` ${bar} ${chalk.bold(`${pct}%`)} ${tag}`);
|
|
3270
|
+
console.log(` ${chalk.white(i.content)}`);
|
|
3271
|
+
if (i.keywords.length > 0) {
|
|
3272
|
+
console.log(` ${chalk.dim(i.keywords.map(k => `#${k}`).join(' '))} ${chalk.dim('·')} ${chalk.dim(`${i.sessions} sessions`)}`);
|
|
3273
|
+
}
|
|
3274
|
+
console.log();
|
|
3204
3275
|
}
|
|
3205
3276
|
}
|
|
3206
3277
|
else {
|
|
3207
|
-
console.log(chalk.dim('
|
|
3278
|
+
console.log(chalk.dim(` ${'─'.repeat(W)}`));
|
|
3279
|
+
console.log();
|
|
3280
|
+
console.log(` ${chalk.dim('No insights yet.')}`);
|
|
3281
|
+
console.log(` ${chalk.dim('Run:')} ${chalk.hex('#A78BFA')('kbot dream run')} ${chalk.dim('to start consolidating memories')}`);
|
|
3282
|
+
console.log();
|
|
3208
3283
|
}
|
|
3209
3284
|
});
|
|
3210
3285
|
dreamCmd
|
|
@@ -3213,24 +3288,137 @@ async function main() {
|
|
|
3213
3288
|
.action(async (query) => {
|
|
3214
3289
|
const { searchDreams } = await import('./dream.js');
|
|
3215
3290
|
const results = searchDreams(query);
|
|
3291
|
+
// Helpers
|
|
3292
|
+
const relevanceBar = (pct, len = 12) => {
|
|
3293
|
+
const filled = Math.round((pct / 100) * len);
|
|
3294
|
+
const empty = len - filled;
|
|
3295
|
+
const color = pct >= 70 ? chalk.hex('#4ADE80') : pct >= 40 ? chalk.hex('#FBBF24') : chalk.hex('#F87171');
|
|
3296
|
+
return color('█'.repeat(filled)) + chalk.dim('░'.repeat(empty));
|
|
3297
|
+
};
|
|
3298
|
+
const categoryColor = (cat) => {
|
|
3299
|
+
const colors = {
|
|
3300
|
+
pattern: '#A78BFA', preference: '#67E8F9', skill: '#4ADE80',
|
|
3301
|
+
project: '#FB923C', relationship: '#F472B6',
|
|
3302
|
+
};
|
|
3303
|
+
return chalk.hex(colors[cat] || '#A78BFA');
|
|
3304
|
+
};
|
|
3305
|
+
const highlightQuery = (text, q) => {
|
|
3306
|
+
const terms = q.toLowerCase().split(/\s+/);
|
|
3307
|
+
let result = text;
|
|
3308
|
+
for (const term of terms) {
|
|
3309
|
+
const regex = new RegExp(`(${term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
|
|
3310
|
+
result = result.replace(regex, chalk.hex('#FBBF24').bold.underline('$1'));
|
|
3311
|
+
}
|
|
3312
|
+
return result;
|
|
3313
|
+
};
|
|
3216
3314
|
if (results.length === 0) {
|
|
3217
|
-
|
|
3315
|
+
console.log();
|
|
3316
|
+
console.log(` ${chalk.hex('#A78BFA')('◆')} ${chalk.bold('Dream Search')} ${chalk.dim(`"${query}"`)}`);
|
|
3317
|
+
console.log();
|
|
3318
|
+
console.log(` ${chalk.dim('No insights match this query.')}`);
|
|
3319
|
+
console.log(` ${chalk.dim('Try broader keywords or run')} ${chalk.hex('#A78BFA')('kbot dream run')} ${chalk.dim('first.')}`);
|
|
3320
|
+
console.log();
|
|
3218
3321
|
return;
|
|
3219
3322
|
}
|
|
3220
|
-
console.log(
|
|
3323
|
+
console.log();
|
|
3324
|
+
console.log(` ${chalk.hex('#A78BFA')('◆')} ${chalk.bold('Dream Search')} ${chalk.dim(`"${query}"`)} ${chalk.hex('#4ADE80')(`${results.length} found`)}`);
|
|
3325
|
+
console.log(chalk.dim(` ${'─'.repeat(52)}`));
|
|
3326
|
+
console.log();
|
|
3221
3327
|
for (const i of results.slice(0, 15)) {
|
|
3222
3328
|
const pct = Math.round(i.relevance * 100);
|
|
3223
|
-
|
|
3224
|
-
|
|
3329
|
+
const bar = relevanceBar(pct);
|
|
3330
|
+
const tag = categoryColor(i.category)(` ${i.category.toUpperCase()} `);
|
|
3331
|
+
console.log(` ${bar} ${chalk.bold(`${pct}%`)} ${tag}`);
|
|
3332
|
+
console.log(` ${highlightQuery(i.content, query)}`);
|
|
3333
|
+
const keywordsHighlighted = i.keywords.map(k => highlightQuery(`#${k}`, query)).join(' ');
|
|
3334
|
+
console.log(` ${keywordsHighlighted} ${chalk.dim('·')} ${chalk.dim(`${i.sessions} sessions`)} ${chalk.dim('·')} ${chalk.dim(i.created.split('T')[0])}`);
|
|
3335
|
+
console.log();
|
|
3225
3336
|
}
|
|
3226
3337
|
});
|
|
3227
3338
|
dreamCmd
|
|
3228
3339
|
.command('journal')
|
|
3229
3340
|
.description('Print the full dream journal')
|
|
3230
3341
|
.action(async () => {
|
|
3231
|
-
const {
|
|
3232
|
-
const
|
|
3233
|
-
|
|
3342
|
+
const { getDreamStatus } = await import('./dream.js');
|
|
3343
|
+
const { state, insights } = getDreamStatus();
|
|
3344
|
+
// Helpers
|
|
3345
|
+
const W = 56;
|
|
3346
|
+
const box = {
|
|
3347
|
+
tl: '╭', tr: '╮', bl: '╰', br: '╯', h: '─', v: '│',
|
|
3348
|
+
pad: (s, w) => {
|
|
3349
|
+
const visible = s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
3350
|
+
const diff = w - visible.length;
|
|
3351
|
+
return diff > 0 ? s + ' '.repeat(diff) : s;
|
|
3352
|
+
},
|
|
3353
|
+
};
|
|
3354
|
+
const relevanceBar = (pct, len = 16) => {
|
|
3355
|
+
const filled = Math.round((pct / 100) * len);
|
|
3356
|
+
const empty = len - filled;
|
|
3357
|
+
const color = pct >= 70 ? chalk.hex('#4ADE80') : pct >= 40 ? chalk.hex('#FBBF24') : chalk.hex('#F87171');
|
|
3358
|
+
return color('█'.repeat(filled)) + chalk.dim('░'.repeat(empty));
|
|
3359
|
+
};
|
|
3360
|
+
const categoryColors = {
|
|
3361
|
+
pattern: '#A78BFA', preference: '#67E8F9', skill: '#4ADE80',
|
|
3362
|
+
project: '#FB923C', relationship: '#F472B6',
|
|
3363
|
+
};
|
|
3364
|
+
const categoryIcon = {
|
|
3365
|
+
pattern: '◇', preference: '♡', skill: '⚡', project: '▸', relationship: '◈',
|
|
3366
|
+
};
|
|
3367
|
+
const categoryColor = (cat) => chalk.hex(categoryColors[cat] || '#A78BFA');
|
|
3368
|
+
if (insights.length === 0) {
|
|
3369
|
+
console.log();
|
|
3370
|
+
console.log(` ${chalk.hex('#A78BFA')('◆')} ${chalk.bold('Dream Journal')}`);
|
|
3371
|
+
console.log();
|
|
3372
|
+
console.log(` ${chalk.dim('The journal is empty.')}`);
|
|
3373
|
+
console.log(` ${chalk.dim('Run')} ${chalk.hex('#A78BFA')('kbot dream run')} ${chalk.dim('after a session to consolidate memories.')}`);
|
|
3374
|
+
console.log();
|
|
3375
|
+
return;
|
|
3376
|
+
}
|
|
3377
|
+
// ── Header ──
|
|
3378
|
+
console.log();
|
|
3379
|
+
console.log(chalk.hex('#A78BFA')(` ${box.tl}${box.h.repeat(W)}${box.tr}`));
|
|
3380
|
+
const headerContent = ` ${chalk.hex('#A78BFA').bold('◆ DREAM JOURNAL')} ${chalk.dim(`${insights.length} insights · cycle ${state.cycles}`)}`;
|
|
3381
|
+
console.log(chalk.hex('#A78BFA')(` ${box.v}`) + box.pad(headerContent, W) + chalk.hex('#A78BFA')(box.v));
|
|
3382
|
+
console.log(chalk.hex('#A78BFA')(` ${box.bl}${box.h.repeat(W)}${box.br}`));
|
|
3383
|
+
console.log();
|
|
3384
|
+
// ── Group by category ──
|
|
3385
|
+
const grouped = {};
|
|
3386
|
+
for (const i of insights) {
|
|
3387
|
+
if (!grouped[i.category])
|
|
3388
|
+
grouped[i.category] = [];
|
|
3389
|
+
grouped[i.category].push(i);
|
|
3390
|
+
}
|
|
3391
|
+
// Sort categories by total insight count descending
|
|
3392
|
+
const catOrder = Object.entries(grouped).sort((a, b) => b[1].length - a[1].length);
|
|
3393
|
+
for (const [cat, catInsights] of catOrder) {
|
|
3394
|
+
const icon = categoryIcon[cat] || '●';
|
|
3395
|
+
const cc = categoryColor(cat);
|
|
3396
|
+
// ── Category section header ──
|
|
3397
|
+
console.log(` ${cc(`${icon} ${cat.toUpperCase()}`)} ${chalk.dim(`(${catInsights.length})`)}`);
|
|
3398
|
+
console.log(` ${cc('─'.repeat(W))}`);
|
|
3399
|
+
console.log();
|
|
3400
|
+
for (const i of catInsights) {
|
|
3401
|
+
const pct = Math.round(i.relevance * 100);
|
|
3402
|
+
const bar = relevanceBar(pct);
|
|
3403
|
+
const date = i.created.split('T')[0];
|
|
3404
|
+
const reinforced = i.lastReinforced !== i.created
|
|
3405
|
+
? chalk.dim(` · reinforced ${i.lastReinforced.split('T')[0]}`)
|
|
3406
|
+
: '';
|
|
3407
|
+
// Card: relevance bar + content + metadata
|
|
3408
|
+
console.log(` ${bar} ${chalk.bold(`${pct}%`)} ${chalk.dim(`${i.sessions} sessions`)}${reinforced}`);
|
|
3409
|
+
console.log(` ${chalk.white(i.content)}`);
|
|
3410
|
+
if (i.keywords.length > 0) {
|
|
3411
|
+
console.log(` ${chalk.dim(i.keywords.map(k => `#${k}`).join(' '))}`);
|
|
3412
|
+
}
|
|
3413
|
+
console.log(` ${chalk.dim(`${date} · ${i.source} · ${i.id}`)}`);
|
|
3414
|
+
console.log();
|
|
3415
|
+
}
|
|
3416
|
+
}
|
|
3417
|
+
// ── Footer ──
|
|
3418
|
+
console.log(chalk.dim(` ${'─'.repeat(W)}`));
|
|
3419
|
+
const avgRel = Math.round(insights.reduce((s, i) => s + i.relevance, 0) / insights.length * 100);
|
|
3420
|
+
console.log(` ${chalk.dim(`${insights.length} active insights · avg relevance ${avgRel}% · ${state.totalArchived} archived`)}`);
|
|
3421
|
+
console.log();
|
|
3234
3422
|
});
|
|
3235
3423
|
program.parse(process.argv);
|
|
3236
3424
|
const opts = program.opts();
|
|
@@ -3973,6 +4161,17 @@ async function startRepl(agentOpts, context, tier, byokActive = false, localActi
|
|
|
3973
4161
|
printInfo(`${p.name}`);
|
|
3974
4162
|
}
|
|
3975
4163
|
const sessionCount = incrementSessions();
|
|
4164
|
+
// Buddy greeting — Tamagotchi companion appears at startup
|
|
4165
|
+
{
|
|
4166
|
+
const buddy = getBuddy();
|
|
4167
|
+
const isFirstRun = sessionCount <= 1 && !existsSync(join(homedir(), '.kbot', 'config.json'));
|
|
4168
|
+
const greeting = isFirstRun
|
|
4169
|
+
? `Hey! I'm ${buddy.name} the ${buddy.species}. Let's set up your API key!`
|
|
4170
|
+
: getBuddyGreeting();
|
|
4171
|
+
console.log();
|
|
4172
|
+
console.log(formatBuddyStatus(greeting));
|
|
4173
|
+
console.log();
|
|
4174
|
+
}
|
|
3976
4175
|
// Seed knowledge on first run — give new users a head start
|
|
3977
4176
|
if (sessionCount <= 2) {
|
|
3978
4177
|
try {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { DreamInsight, DreamCategory } from './dream.js';
|
|
2
|
+
export interface AnonymizedInsight {
|
|
3
|
+
/** Category preserved as-is */
|
|
4
|
+
category: DreamCategory;
|
|
5
|
+
/** Keywords with PII stripped */
|
|
6
|
+
keywords: string[];
|
|
7
|
+
/** Generalized version of the content (no personal details) */
|
|
8
|
+
generalizedContent: string;
|
|
9
|
+
/** How many contributors have shared similar insights */
|
|
10
|
+
contributorCount: number;
|
|
11
|
+
/** First time this insight appeared in the collective */
|
|
12
|
+
firstSeen: string;
|
|
13
|
+
/** Most recent contribution timestamp */
|
|
14
|
+
lastSeen: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Anonymize a single dream insight for collective sharing.
|
|
18
|
+
* Strips personal info, keeps only category, keywords, and generalized content.
|
|
19
|
+
*/
|
|
20
|
+
export declare function anonymizeDreamInsight(insight: DreamInsight): AnonymizedInsight;
|
|
21
|
+
/**
|
|
22
|
+
* Prepare a batch of dream insights for collective sharing.
|
|
23
|
+
* 1. Filter to high-relevance insights (> 0.7)
|
|
24
|
+
* 2. Anonymize each
|
|
25
|
+
* 3. Deduplicate by content similarity
|
|
26
|
+
*/
|
|
27
|
+
export declare function prepareCollectiveDreams(insights: DreamInsight[]): AnonymizedInsight[];
|
|
28
|
+
/**
|
|
29
|
+
* Merge collective wisdom into the local dream journal.
|
|
30
|
+
*
|
|
31
|
+
* Collective insights are injected with a lower base relevance (0.5) so they
|
|
32
|
+
* don't drown out the user's own insights but still surface when relevant.
|
|
33
|
+
* Deduplicates against existing local insights by content similarity.
|
|
34
|
+
*/
|
|
35
|
+
export declare function mergeCollectiveDreams(local: DreamInsight[], collective: AnonymizedInsight[]): DreamInsight[];
|
|
36
|
+
//# sourceMappingURL=collective-dreams.d.ts.map
|