@kernel.chat/kbot 2.5.0 → 2.8.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 +98 -42
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +140 -21
- package/dist/agent.js.map +1 -1
- package/dist/architect.d.ts +44 -0
- package/dist/architect.d.ts.map +1 -0
- package/dist/architect.js +403 -0
- package/dist/architect.js.map +1 -0
- package/dist/auth.d.ts +11 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +165 -7
- package/dist/auth.js.map +1 -1
- package/dist/cli.js +251 -22
- package/dist/cli.js.map +1 -1
- package/dist/graph-memory.d.ts +98 -0
- package/dist/graph-memory.d.ts.map +1 -0
- package/dist/graph-memory.js +926 -0
- package/dist/graph-memory.js.map +1 -0
- package/dist/ide/acp-server.js +2 -2
- package/dist/ide/mcp-server.js +1 -1
- package/dist/lsp-client.d.ts +167 -0
- package/dist/lsp-client.d.ts.map +1 -0
- package/dist/lsp-client.js +679 -0
- package/dist/lsp-client.js.map +1 -0
- package/dist/matrix.d.ts +6 -0
- package/dist/matrix.d.ts.map +1 -1
- package/dist/matrix.js +98 -0
- package/dist/matrix.js.map +1 -1
- package/dist/mcp-plugins.d.ts +62 -0
- package/dist/mcp-plugins.d.ts.map +1 -0
- package/dist/mcp-plugins.js +551 -0
- package/dist/mcp-plugins.js.map +1 -0
- package/dist/planner.d.ts.map +1 -1
- package/dist/planner.js +29 -0
- package/dist/planner.js.map +1 -1
- package/dist/provider-fallback.d.ts +51 -0
- package/dist/provider-fallback.d.ts.map +1 -0
- package/dist/provider-fallback.js +237 -0
- package/dist/provider-fallback.js.map +1 -0
- package/dist/repo-map.d.ts +9 -0
- package/dist/repo-map.d.ts.map +1 -0
- package/dist/repo-map.js +280 -0
- package/dist/repo-map.js.map +1 -0
- package/dist/self-eval.d.ts +45 -0
- package/dist/self-eval.d.ts.map +1 -0
- package/dist/self-eval.js +232 -0
- package/dist/self-eval.js.map +1 -0
- package/dist/streaming.d.ts.map +1 -1
- package/dist/streaming.js +22 -2
- package/dist/streaming.js.map +1 -1
- package/dist/task-ledger.d.ts +71 -0
- package/dist/task-ledger.d.ts.map +1 -0
- package/dist/task-ledger.js +282 -0
- package/dist/task-ledger.js.map +1 -0
- package/dist/tools/computer.js +3 -3
- package/dist/tools/computer.js.map +1 -1
- package/dist/tools/e2b-sandbox.d.ts +2 -0
- package/dist/tools/e2b-sandbox.d.ts.map +1 -0
- package/dist/tools/e2b-sandbox.js +460 -0
- package/dist/tools/e2b-sandbox.js.map +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +15 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/lsp-tools.d.ts +2 -0
- package/dist/tools/lsp-tools.d.ts.map +1 -0
- package/dist/tools/lsp-tools.js +268 -0
- package/dist/tools/lsp-tools.js.map +1 -0
- package/dist/tools/memory-tools.d.ts +2 -0
- package/dist/tools/memory-tools.d.ts.map +1 -0
- package/dist/tools/memory-tools.js +228 -0
- package/dist/tools/memory-tools.js.map +1 -0
- package/dist/tools/quality.d.ts +2 -0
- package/dist/tools/quality.d.ts.map +1 -0
- package/dist/tools/quality.js +313 -0
- package/dist/tools/quality.js.map +1 -0
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +33 -18
- package/dist/ui.js.map +1 -1
- package/package.json +27 -3
package/dist/cli.js
CHANGED
|
@@ -16,20 +16,20 @@ import { gatherContext } from './context.js';
|
|
|
16
16
|
import { registerAllTools } from './tools/index.js';
|
|
17
17
|
import { clearHistory, clearMemory, compactHistory, restoreHistory } from './memory.js';
|
|
18
18
|
import { saveSession, loadSession, listSessions, deleteSession, formatSessionList, } from './sessions.js';
|
|
19
|
-
import { createAgent, removeAgent, getAgent, formatAgentList, formatAgentDetail, PRESETS, getMatrixAgentIds, activateMimic, listMimicProfiles, getMimicProfile, } from './matrix.js';
|
|
19
|
+
import { createAgent, removeAgent, getAgent, formatAgentList, formatAgentDetail, PRESETS, getMatrixAgentIds, activateMimic, listMimicProfiles, getMimicProfile, registerBuiltinAgents, formatBuiltinAgentList, formatBuiltinAgentDetail, } from './matrix.js';
|
|
20
20
|
import { getExtendedStats, incrementSessions, learnFact, selfTrain, getTrainingLog, flushPendingWrites } from './learning.js';
|
|
21
21
|
import { banner, bannerCompact, bannerAuth, prompt as kbotPrompt, printError, printSuccess, printInfo, printResponse, printHelp, printGoodbye, setQuiet, } from './ui.js';
|
|
22
22
|
import { checkForUpdate, selfUpdate } from './updater.js';
|
|
23
23
|
import { syncOnStartup, schedulePush, flushCloudSync, isCloudSyncEnabled, setCloudToken, getCloudToken } from './cloud-sync.js';
|
|
24
24
|
import chalk from 'chalk';
|
|
25
|
-
const VERSION = '2.
|
|
25
|
+
const VERSION = '2.8.0';
|
|
26
26
|
async function main() {
|
|
27
27
|
const program = new Command();
|
|
28
28
|
program
|
|
29
29
|
.name('kbot')
|
|
30
30
|
.description('K:BOT — Open-source terminal AI agent. Bring your own key, pick your model, run locally.')
|
|
31
31
|
.version(VERSION)
|
|
32
|
-
.option('-a, --agent <agent>', 'Force a specific agent (kernel, researcher, coder, writer, analyst)')
|
|
32
|
+
.option('-a, --agent <agent>', 'Force a specific agent (kernel, researcher, coder, writer, analyst, hacker, operator, dreamer)')
|
|
33
33
|
.option('-m, --model <model>', 'Override AI model (auto, sonnet, haiku)')
|
|
34
34
|
.option('-s, --stream', 'Stream the response')
|
|
35
35
|
.option('-p, --pipe', 'Pipe mode — raw text output for scripting')
|
|
@@ -40,6 +40,8 @@ async function main() {
|
|
|
40
40
|
.option('--computer-use', 'Enable computer use tools')
|
|
41
41
|
.option('-t, --thinking', 'Show AI reasoning steps')
|
|
42
42
|
.option('--thinking-budget <tokens>', 'Thinking token budget (default: 10000)')
|
|
43
|
+
.option('--self-eval', 'Enable self-evaluation loop (score and retry low-quality responses)')
|
|
44
|
+
.option('--architect', 'Architect mode — plan-review-implement with dual agents')
|
|
43
45
|
.option('--safe', 'Confirm destructive operations')
|
|
44
46
|
.option('--strict', 'Confirm ALL operations')
|
|
45
47
|
.argument('[prompt...]', 'One-shot prompt')
|
|
@@ -86,7 +88,7 @@ async function main() {
|
|
|
86
88
|
});
|
|
87
89
|
program
|
|
88
90
|
.command('byok')
|
|
89
|
-
.description('Bring Your Own Key — configure your LLM API key (
|
|
91
|
+
.description('Bring Your Own Key — configure your LLM API key (19 providers)')
|
|
90
92
|
.option('--off', 'Disable BYOK mode')
|
|
91
93
|
.action(async (opts) => {
|
|
92
94
|
if (opts.off) {
|
|
@@ -370,7 +372,7 @@ async function main() {
|
|
|
370
372
|
});
|
|
371
373
|
program
|
|
372
374
|
.command('serve')
|
|
373
|
-
.description('Start HTTP server — expose all
|
|
375
|
+
.description('Start HTTP server — expose all 119 tools for kernel.chat or any client')
|
|
374
376
|
.option('-p, --port <port>', 'Port to listen on', '7437')
|
|
375
377
|
.option('--token <token>', 'Require auth token for all requests')
|
|
376
378
|
.option('--computer-use', 'Enable computer use tools')
|
|
@@ -401,6 +403,27 @@ async function main() {
|
|
|
401
403
|
printError('Cannot connect to OpenClaw gateway. Start it first.');
|
|
402
404
|
}
|
|
403
405
|
});
|
|
406
|
+
program
|
|
407
|
+
.command('agents [name]')
|
|
408
|
+
.description('List all available agents, or show details for one')
|
|
409
|
+
.action(async (name) => {
|
|
410
|
+
registerBuiltinAgents();
|
|
411
|
+
if (name) {
|
|
412
|
+
const detail = formatBuiltinAgentDetail(name);
|
|
413
|
+
if (detail) {
|
|
414
|
+
console.log(detail);
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
printError(`Agent "${name}" not found.`);
|
|
418
|
+
printInfo('Run `kbot agents` to see all available agents.');
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
console.log(formatBuiltinAgentList());
|
|
423
|
+
console.log();
|
|
424
|
+
printInfo('Use: kbot --agent <name> "prompt"');
|
|
425
|
+
}
|
|
426
|
+
});
|
|
404
427
|
program.parse(process.argv);
|
|
405
428
|
const opts = program.opts();
|
|
406
429
|
const promptArgs = program.args;
|
|
@@ -408,7 +431,7 @@ async function main() {
|
|
|
408
431
|
if (opts.quiet)
|
|
409
432
|
setQuiet(true);
|
|
410
433
|
// If a sub-command was run, we're done
|
|
411
|
-
if (['byok', 'auth', 'ide', 'ollama', 'openclaw', 'pull', 'doctor', 'serve'].includes(program.args[0]))
|
|
434
|
+
if (['byok', 'auth', 'ide', 'ollama', 'openclaw', 'pull', 'doctor', 'serve', 'agents'].includes(program.args[0]))
|
|
412
435
|
return;
|
|
413
436
|
// Check for API key (BYOK or local provider)
|
|
414
437
|
let byokActive = isByokEnabled();
|
|
@@ -422,9 +445,10 @@ async function main() {
|
|
|
422
445
|
localActive = isLocalProvider(envDetected);
|
|
423
446
|
printSuccess(`Auto-detected ${PROVIDERS[envDetected].name} from environment.`);
|
|
424
447
|
}
|
|
425
|
-
// Priority 2: Check local providers in PARALLEL (
|
|
448
|
+
// Priority 2: Check local providers in PARALLEL (all at once, use whichever responds first)
|
|
426
449
|
if (!byokActive) {
|
|
427
|
-
const
|
|
450
|
+
const { isLmStudioRunning, isJanRunning, setupLmStudio, setupJan } = await import('./auth.js');
|
|
451
|
+
const [ollamaResult, lmstudioResult, janResult, openclawResult] = await Promise.allSettled([
|
|
428
452
|
// Check Ollama
|
|
429
453
|
(async () => {
|
|
430
454
|
const up = await isOllamaRunning();
|
|
@@ -436,6 +460,22 @@ async function main() {
|
|
|
436
460
|
const ok = await setupOllama();
|
|
437
461
|
return ok ? { provider: 'ollama', models: models.length } : null;
|
|
438
462
|
})(),
|
|
463
|
+
// Check LM Studio
|
|
464
|
+
(async () => {
|
|
465
|
+
const up = await isLmStudioRunning();
|
|
466
|
+
if (!up)
|
|
467
|
+
return null;
|
|
468
|
+
const ok = await setupLmStudio();
|
|
469
|
+
return ok ? { provider: 'lmstudio' } : null;
|
|
470
|
+
})(),
|
|
471
|
+
// Check Jan
|
|
472
|
+
(async () => {
|
|
473
|
+
const up = await isJanRunning();
|
|
474
|
+
if (!up)
|
|
475
|
+
return null;
|
|
476
|
+
const ok = await setupJan();
|
|
477
|
+
return ok ? { provider: 'jan' } : null;
|
|
478
|
+
})(),
|
|
439
479
|
// Check OpenClaw
|
|
440
480
|
(async () => {
|
|
441
481
|
try {
|
|
@@ -450,14 +490,26 @@ async function main() {
|
|
|
450
490
|
}
|
|
451
491
|
})(),
|
|
452
492
|
]);
|
|
453
|
-
// Prefer Ollama
|
|
493
|
+
// Prefer Ollama > LM Studio > Jan > OpenClaw
|
|
454
494
|
const ollamaOk = ollamaResult.status === 'fulfilled' && ollamaResult.value;
|
|
495
|
+
const lmstudioOk = lmstudioResult.status === 'fulfilled' && lmstudioResult.value;
|
|
496
|
+
const janOk = janResult.status === 'fulfilled' && janResult.value;
|
|
455
497
|
const openclawOk = openclawResult.status === 'fulfilled' && openclawResult.value;
|
|
456
498
|
if (ollamaOk) {
|
|
457
499
|
byokActive = true;
|
|
458
500
|
localActive = true;
|
|
459
501
|
printSuccess(`Auto-configured Ollama (${ollamaOk.models} models). Ready — $0 cost!`);
|
|
460
502
|
}
|
|
503
|
+
else if (lmstudioOk) {
|
|
504
|
+
byokActive = true;
|
|
505
|
+
localActive = true;
|
|
506
|
+
printSuccess('Auto-configured LM Studio. Ready — $0 cost!');
|
|
507
|
+
}
|
|
508
|
+
else if (janOk) {
|
|
509
|
+
byokActive = true;
|
|
510
|
+
localActive = true;
|
|
511
|
+
printSuccess('Auto-configured Jan. Ready — $0 cost!');
|
|
512
|
+
}
|
|
461
513
|
else if (openclawOk) {
|
|
462
514
|
byokActive = true;
|
|
463
515
|
localActive = true;
|
|
@@ -488,6 +540,9 @@ async function main() {
|
|
|
488
540
|
{ env: 'PERPLEXITY_API_KEY', provider: 'perplexity' },
|
|
489
541
|
{ env: 'COHERE_API_KEY', provider: 'cohere' },
|
|
490
542
|
{ env: 'NVIDIA_API_KEY', provider: 'nvidia' },
|
|
543
|
+
{ env: 'SAMBANOVA_API_KEY', provider: 'sambanova' },
|
|
544
|
+
{ env: 'CEREBRAS_API_KEY', provider: 'cerebras' },
|
|
545
|
+
{ env: 'OPENROUTER_API_KEY', provider: 'openrouter' },
|
|
491
546
|
];
|
|
492
547
|
for (const { env, provider } of envKeys) {
|
|
493
548
|
if (process.env[env])
|
|
@@ -513,6 +568,8 @@ async function main() {
|
|
|
513
568
|
setPermissionMode('permissive');
|
|
514
569
|
}
|
|
515
570
|
}
|
|
571
|
+
// Register built-in agents (hacker, operator, dreamer) so --agent flag works
|
|
572
|
+
registerBuiltinAgents();
|
|
516
573
|
// Parallel startup: register tools, gather context, check updates, and cloud sync
|
|
517
574
|
const [, context, , syncMsg] = await Promise.all([
|
|
518
575
|
registerAllTools({ computerUse: opts.computerUse }),
|
|
@@ -542,6 +599,11 @@ async function main() {
|
|
|
542
599
|
thinking: opts.thinking || false,
|
|
543
600
|
thinkingBudget: opts.thinkingBudget ? (parseInt(opts.thinkingBudget, 10) || 10000) : undefined,
|
|
544
601
|
};
|
|
602
|
+
// Enable self-evaluation if requested
|
|
603
|
+
if (opts.selfEval) {
|
|
604
|
+
const { setSelfEvalEnabled } = await import('./self-eval.js');
|
|
605
|
+
setSelfEvalEnabled(true);
|
|
606
|
+
}
|
|
545
607
|
// Pipe mode: echo "prompt" | kbot -p OR kbot -p "prompt"
|
|
546
608
|
if (opts.pipe) {
|
|
547
609
|
let message = promptArgs.join(' ');
|
|
@@ -639,6 +701,12 @@ async function main() {
|
|
|
639
701
|
}) + '\n');
|
|
640
702
|
return;
|
|
641
703
|
}
|
|
704
|
+
// Architect mode: plan-review-implement with dual agents
|
|
705
|
+
if (opts.architect) {
|
|
706
|
+
const { runArchitectMode } = await import('./architect.js');
|
|
707
|
+
await runArchitectMode(message, agentOpts);
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
642
710
|
agentOpts.stream = true; // Force streaming for faster one-shot
|
|
643
711
|
await runAndPrint(message, agentOpts);
|
|
644
712
|
return;
|
|
@@ -739,12 +807,13 @@ async function byokFlow() {
|
|
|
739
807
|
async function guidedSetup() {
|
|
740
808
|
console.log(banner(VERSION));
|
|
741
809
|
console.log();
|
|
742
|
-
console.log(chalk.bold('
|
|
810
|
+
console.log(chalk.bold(' Hey! I\'m K:BOT — your AI assistant for the terminal.'));
|
|
743
811
|
console.log();
|
|
744
|
-
console.log(chalk.dim('
|
|
812
|
+
console.log(chalk.dim(' I can write code, answer questions, search the web, manage git,'));
|
|
813
|
+
console.log(chalk.dim(' and a lot more. First, I need an AI brain. Pick one:'));
|
|
745
814
|
console.log();
|
|
746
|
-
console.log(` ${chalk.bold('1.')} ${chalk.hex('#6B8E6B')('Free & Private')} — Run AI on your computer (no account
|
|
747
|
-
console.log(` ${chalk.bold('2.')} ${chalk.hex('#5B8BA0')('Cloud AI')} — Use an API key
|
|
815
|
+
console.log(` ${chalk.bold('1.')} ${chalk.hex('#6B8E6B')('Free & Private')} — Run AI on your computer (no account, no cost)`);
|
|
816
|
+
console.log(` ${chalk.bold('2.')} ${chalk.hex('#5B8BA0')('Cloud AI')} — Use an API key (OpenAI, Google, Anthropic, etc.)`);
|
|
748
817
|
console.log();
|
|
749
818
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
750
819
|
const choice = await new Promise((resolve) => {
|
|
@@ -885,14 +954,48 @@ async function startRepl(agentOpts, context, tier, byokActive = false, localActi
|
|
|
885
954
|
printInfo(`${p.name}`);
|
|
886
955
|
}
|
|
887
956
|
const sessionCount = incrementSessions();
|
|
957
|
+
// Return-visit greeting — show kbot's growth
|
|
958
|
+
if (sessionCount > 1) {
|
|
959
|
+
const stats = getExtendedStats();
|
|
960
|
+
const parts = [];
|
|
961
|
+
if (stats.patternsCount > 0)
|
|
962
|
+
parts.push(`${stats.patternsCount} patterns learned`);
|
|
963
|
+
if (stats.solutionsCount > 0)
|
|
964
|
+
parts.push(`${stats.solutionsCount} solutions cached`);
|
|
965
|
+
if (stats.knowledgeCount > 0)
|
|
966
|
+
parts.push(`${stats.knowledgeCount} facts remembered`);
|
|
967
|
+
if (parts.length > 0) {
|
|
968
|
+
printInfo(`Session ${stats.sessions} · ${parts.join(' · ')}`);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
888
971
|
const rl = createInterface({
|
|
889
972
|
input: process.stdin,
|
|
890
973
|
output: process.stdout,
|
|
891
974
|
prompt: kbotPrompt(),
|
|
892
975
|
});
|
|
893
|
-
// First time? Show a
|
|
976
|
+
// First time? Show a friendly walkthrough
|
|
894
977
|
if (sessionCount <= 1) {
|
|
895
|
-
|
|
978
|
+
console.log();
|
|
979
|
+
console.log(chalk.dim(' ┌─────────────────────────────────────────────┐'));
|
|
980
|
+
console.log(chalk.dim(' │') + chalk.bold(' Welcome! Here are some things you can try: ') + chalk.dim(' │'));
|
|
981
|
+
console.log(chalk.dim(' │ │'));
|
|
982
|
+
console.log(chalk.dim(' │') + ' "explain this project" ' + chalk.dim(' │'));
|
|
983
|
+
console.log(chalk.dim(' │') + ' "write a function that sorts names" ' + chalk.dim(' │'));
|
|
984
|
+
console.log(chalk.dim(' │') + ' "find all TODO comments in this repo" ' + chalk.dim(' │'));
|
|
985
|
+
console.log(chalk.dim(' │') + ' "what files are in this directory?" ' + chalk.dim(' │'));
|
|
986
|
+
console.log(chalk.dim(' │ │'));
|
|
987
|
+
console.log(chalk.dim(' │') + chalk.dim(' Type /help for more commands. ') + chalk.dim(' │'));
|
|
988
|
+
console.log(chalk.dim(' └─────────────────────────────────────────────┘'));
|
|
989
|
+
console.log();
|
|
990
|
+
}
|
|
991
|
+
else if (sessionCount <= 3) {
|
|
992
|
+
// Second and third time — show a quick tip they might not know
|
|
993
|
+
const tips = [
|
|
994
|
+
'Tip: kbot picks the right specialist for you. Try asking about science, code, or writing.',
|
|
995
|
+
'Tip: Type /save to keep this conversation. /resume to pick it up later.',
|
|
996
|
+
'Tip: kbot learns from you. The more you use it, the better it gets.',
|
|
997
|
+
];
|
|
998
|
+
printInfo(tips[Math.min(sessionCount - 1, tips.length - 1)]);
|
|
896
999
|
}
|
|
897
1000
|
console.log();
|
|
898
1001
|
rl.prompt();
|
|
@@ -929,12 +1032,28 @@ async function startRepl(agentOpts, context, tier, byokActive = false, localActi
|
|
|
929
1032
|
if (!response.streamed) {
|
|
930
1033
|
printResponse(response.agent, response.content);
|
|
931
1034
|
}
|
|
932
|
-
//
|
|
933
|
-
|
|
934
|
-
const
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
1035
|
+
// Mentor footer — teach the user what kbot did (agent, tools, cost)
|
|
1036
|
+
{
|
|
1037
|
+
const parts = [];
|
|
1038
|
+
// Show which agent handled it (teaches routing)
|
|
1039
|
+
if (response.agent && response.agent !== 'kernel') {
|
|
1040
|
+
parts.push(`${response.agent} agent`);
|
|
1041
|
+
}
|
|
1042
|
+
if (response.toolCalls > 0) {
|
|
1043
|
+
parts.push(`${response.toolCalls} tool${response.toolCalls > 1 ? 's' : ''} used`);
|
|
1044
|
+
}
|
|
1045
|
+
if (response.usage) {
|
|
1046
|
+
const tokens = response.usage.input_tokens + response.usage.output_tokens;
|
|
1047
|
+
const cost = response.usage.cost_usd === 0 ? 'free' : `$${response.usage.cost_usd.toFixed(4)}`;
|
|
1048
|
+
parts.push(`${tokens} tokens · ${cost}`);
|
|
1049
|
+
}
|
|
1050
|
+
if (parts.length > 0) {
|
|
1051
|
+
printInfo(parts.join(' · '));
|
|
1052
|
+
}
|
|
1053
|
+
// On first 5 sessions, teach what just happened
|
|
1054
|
+
if (sessionCount <= 5 && response.agent && response.agent !== 'kernel') {
|
|
1055
|
+
printInfo(chalk.dim(` I picked the ${response.agent} agent for this. You can also say /agent ${response.agent} to use it directly.`));
|
|
1056
|
+
}
|
|
938
1057
|
}
|
|
939
1058
|
// Schedule cloud sync push (debounced — batches writes)
|
|
940
1059
|
schedulePush();
|
|
@@ -1071,6 +1190,47 @@ async function handleSlashCommand(input, opts, rl) {
|
|
|
1071
1190
|
case 'help':
|
|
1072
1191
|
printHelp();
|
|
1073
1192
|
break;
|
|
1193
|
+
case 'tutorial': {
|
|
1194
|
+
console.log();
|
|
1195
|
+
console.log(chalk.bold(' Let\'s build something together. Pick a track:'));
|
|
1196
|
+
console.log();
|
|
1197
|
+
console.log(` ${chalk.bold('1.')} ${chalk.hex('#4ADE80')('Build a website')} — Create an HTML page from scratch`);
|
|
1198
|
+
console.log(` ${chalk.bold('2.')} ${chalk.hex('#60A5FA')('Fix a bug')} — Find and fix a problem in code`);
|
|
1199
|
+
console.log(` ${chalk.bold('3.')} ${chalk.hex('#FB923C')('Write a script')} — Automate something with Python or JavaScript`);
|
|
1200
|
+
console.log(` ${chalk.bold('4.')} ${chalk.hex('#F472B6')('Research a topic')} — Deep-dive into any subject`);
|
|
1201
|
+
console.log(` ${chalk.bold('5.')} ${chalk.hex('#A78BFA')('Explore this project')} — Understand the code in this folder`);
|
|
1202
|
+
console.log();
|
|
1203
|
+
console.log(chalk.dim(' Pick a number, or just type what you want to build.'));
|
|
1204
|
+
console.log();
|
|
1205
|
+
const tutorialInput = await new Promise((resolve) => {
|
|
1206
|
+
rl.question(' Your choice: ', (answer) => resolve(answer.trim()));
|
|
1207
|
+
});
|
|
1208
|
+
const tutorialPrompts = {
|
|
1209
|
+
'1': 'Create a simple, beautiful HTML page with a heading, a paragraph about me, and some CSS styling. Save it as index.html. Walk me through what each part does.',
|
|
1210
|
+
'2': 'Look at the files in this directory. Find any issues, bugs, or things that could be improved. Explain what you found and fix the most important one.',
|
|
1211
|
+
'3': 'Write a short script that lists all files in the current directory, sorted by size. Use the language that makes the most sense for this project. Explain each line.',
|
|
1212
|
+
'4': 'I want to understand how AI agents work. Research this topic and explain it simply — what are agents, how do they think, and what tools do they use? Give real examples.',
|
|
1213
|
+
'5': 'Explore this project directory. What language is it written in? What does it do? What are the most important files? Give me a quick tour.',
|
|
1214
|
+
};
|
|
1215
|
+
const prompt = tutorialPrompts[tutorialInput] || tutorialInput;
|
|
1216
|
+
if (prompt) {
|
|
1217
|
+
console.log();
|
|
1218
|
+
printInfo('Great choice! Let me work on that...');
|
|
1219
|
+
console.log();
|
|
1220
|
+
try {
|
|
1221
|
+
const response = await runAgent(prompt, opts);
|
|
1222
|
+
if (!response.streamed) {
|
|
1223
|
+
printResponse(response.agent, response.content);
|
|
1224
|
+
}
|
|
1225
|
+
console.log();
|
|
1226
|
+
printInfo(chalk.dim('That\'s the basics! Keep asking questions — I learn from every conversation.'));
|
|
1227
|
+
}
|
|
1228
|
+
catch (err) {
|
|
1229
|
+
printError(err instanceof Error ? err.message : String(err));
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
break;
|
|
1233
|
+
}
|
|
1074
1234
|
case 'agent':
|
|
1075
1235
|
if (args[0]) {
|
|
1076
1236
|
opts.agent = args[0];
|
|
@@ -1241,6 +1401,74 @@ async function handleSlashCommand(input, opts, rl) {
|
|
|
1241
1401
|
if (opts.thinking)
|
|
1242
1402
|
printInfo('AI will show reasoning steps before responding.');
|
|
1243
1403
|
break;
|
|
1404
|
+
case 'self-eval':
|
|
1405
|
+
case 'selfeval': {
|
|
1406
|
+
const { isSelfEvalEnabled, setSelfEvalEnabled } = await import('./self-eval.js');
|
|
1407
|
+
const newState = !isSelfEvalEnabled();
|
|
1408
|
+
setSelfEvalEnabled(newState);
|
|
1409
|
+
printSuccess(`Self-evaluation: ${newState ? 'ON' : 'OFF'}`);
|
|
1410
|
+
if (newState)
|
|
1411
|
+
printInfo('Responses will be scored for quality and retried if below threshold.');
|
|
1412
|
+
break;
|
|
1413
|
+
}
|
|
1414
|
+
case 'health':
|
|
1415
|
+
case 'providers': {
|
|
1416
|
+
const { getProviderHealth } = await import('./provider-fallback.js');
|
|
1417
|
+
const health = getProviderHealth();
|
|
1418
|
+
const active = health.filter(h => h.lastSuccess || h.lastFailure);
|
|
1419
|
+
if (active.length === 0) {
|
|
1420
|
+
printInfo('No provider calls recorded yet.');
|
|
1421
|
+
}
|
|
1422
|
+
else {
|
|
1423
|
+
console.log();
|
|
1424
|
+
printInfo('Provider Health:');
|
|
1425
|
+
for (const h of active) {
|
|
1426
|
+
const status = h.isHealthy ? chalk.green('healthy') : chalk.red('unhealthy');
|
|
1427
|
+
const latency = h.avgLatencyMs ? `${h.avgLatencyMs}ms` : '-';
|
|
1428
|
+
const failures = h.consecutiveFailures > 0 ? chalk.yellow(` (${h.consecutiveFailures} failures)`) : '';
|
|
1429
|
+
printInfo(` ${h.provider}: ${status} · ${latency}${failures}`);
|
|
1430
|
+
}
|
|
1431
|
+
console.log();
|
|
1432
|
+
}
|
|
1433
|
+
break;
|
|
1434
|
+
}
|
|
1435
|
+
case 'architect': {
|
|
1436
|
+
const archTask = args.join(' ');
|
|
1437
|
+
if (!archTask) {
|
|
1438
|
+
printError('Usage: /architect <task description>');
|
|
1439
|
+
printInfo('Example: /architect refactor the auth system to use JWT');
|
|
1440
|
+
}
|
|
1441
|
+
else {
|
|
1442
|
+
const { runArchitectMode } = await import('./architect.js');
|
|
1443
|
+
await runArchitectMode(archTask, opts);
|
|
1444
|
+
}
|
|
1445
|
+
break;
|
|
1446
|
+
}
|
|
1447
|
+
case 'graph': {
|
|
1448
|
+
const graphArgs = args.join(' ');
|
|
1449
|
+
if (!graphArgs) {
|
|
1450
|
+
const { getGraph } = await import('./graph-memory.js');
|
|
1451
|
+
const graph = getGraph();
|
|
1452
|
+
printInfo(`Graph: ${graph.nodes.size} nodes, ${graph.edges.length} edges`);
|
|
1453
|
+
if (graph.nodes.size > 0) {
|
|
1454
|
+
const { toContext } = await import('./graph-memory.js');
|
|
1455
|
+
printInfo(toContext(500));
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
else {
|
|
1459
|
+
const { findNode } = await import('./graph-memory.js');
|
|
1460
|
+
const results = findNode(graphArgs);
|
|
1461
|
+
if (results.length === 0) {
|
|
1462
|
+
printInfo('No matching nodes found.');
|
|
1463
|
+
}
|
|
1464
|
+
else {
|
|
1465
|
+
for (const n of results.slice(0, 10)) {
|
|
1466
|
+
printInfo(` [${n.type}:${n.name}] (${n.accessCount} accesses)`);
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
break;
|
|
1471
|
+
}
|
|
1244
1472
|
case 'plan': {
|
|
1245
1473
|
const planTask = args.join(' ');
|
|
1246
1474
|
if (!planTask) {
|
|
@@ -1513,7 +1741,8 @@ async function handleSlashCommand(input, opts, rl) {
|
|
|
1513
1741
|
rl.close();
|
|
1514
1742
|
break;
|
|
1515
1743
|
default:
|
|
1516
|
-
printError(`
|
|
1744
|
+
printError(`I don't know "/${cmd}". Here are some you can try:`);
|
|
1745
|
+
printInfo(' /save — save this chat | /agent — pick a specialist | /help — see everything');
|
|
1517
1746
|
}
|
|
1518
1747
|
}
|
|
1519
1748
|
// Prevent unhandled rejections from killing the process
|