@kernel.chat/kbot 2.4.0 → 2.7.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 +116 -21
- package/dist/agent.js.map +1 -1
- 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 +220 -21
- package/dist/cli.js.map +1 -1
- package/dist/ide/acp-server.js +2 -2
- package/dist/ide/acp-server.js.map +1 -1
- package/dist/ide/mcp-server.js +1 -1
- 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/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/serve.d.ts +8 -0
- package/dist/serve.d.ts.map +1 -0
- package/dist/serve.js +159 -0
- package/dist/serve.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/index.d.ts.map +1 -1
- package/dist/tools/index.js +7 -1
- package/dist/tools/index.js.map +1 -1
- 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.7.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,7 @@ 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)')
|
|
43
44
|
.option('--safe', 'Confirm destructive operations')
|
|
44
45
|
.option('--strict', 'Confirm ALL operations')
|
|
45
46
|
.argument('[prompt...]', 'One-shot prompt')
|
|
@@ -86,7 +87,7 @@ async function main() {
|
|
|
86
87
|
});
|
|
87
88
|
program
|
|
88
89
|
.command('byok')
|
|
89
|
-
.description('Bring Your Own Key — configure your LLM API key (
|
|
90
|
+
.description('Bring Your Own Key — configure your LLM API key (19 providers)')
|
|
90
91
|
.option('--off', 'Disable BYOK mode')
|
|
91
92
|
.action(async (opts) => {
|
|
92
93
|
if (opts.off) {
|
|
@@ -368,6 +369,20 @@ async function main() {
|
|
|
368
369
|
printInfo(`Or pull all: ${missing.map(m => `ollama pull ${m.name}`).join(' && ')}`);
|
|
369
370
|
}
|
|
370
371
|
});
|
|
372
|
+
program
|
|
373
|
+
.command('serve')
|
|
374
|
+
.description('Start HTTP server — expose all 93 tools for kernel.chat or any client')
|
|
375
|
+
.option('-p, --port <port>', 'Port to listen on', '7437')
|
|
376
|
+
.option('--token <token>', 'Require auth token for all requests')
|
|
377
|
+
.option('--computer-use', 'Enable computer use tools')
|
|
378
|
+
.action(async (opts) => {
|
|
379
|
+
const { startServe } = await import('./serve.js');
|
|
380
|
+
await startServe({
|
|
381
|
+
port: parseInt(opts.port, 10),
|
|
382
|
+
token: opts.token,
|
|
383
|
+
computerUse: opts.computerUse,
|
|
384
|
+
});
|
|
385
|
+
});
|
|
371
386
|
program
|
|
372
387
|
.command('openclaw')
|
|
373
388
|
.description('Use OpenClaw gateway as AI provider')
|
|
@@ -387,6 +402,27 @@ async function main() {
|
|
|
387
402
|
printError('Cannot connect to OpenClaw gateway. Start it first.');
|
|
388
403
|
}
|
|
389
404
|
});
|
|
405
|
+
program
|
|
406
|
+
.command('agents [name]')
|
|
407
|
+
.description('List all available agents, or show details for one')
|
|
408
|
+
.action(async (name) => {
|
|
409
|
+
registerBuiltinAgents();
|
|
410
|
+
if (name) {
|
|
411
|
+
const detail = formatBuiltinAgentDetail(name);
|
|
412
|
+
if (detail) {
|
|
413
|
+
console.log(detail);
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
printError(`Agent "${name}" not found.`);
|
|
417
|
+
printInfo('Run `kbot agents` to see all available agents.');
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
console.log(formatBuiltinAgentList());
|
|
422
|
+
console.log();
|
|
423
|
+
printInfo('Use: kbot --agent <name> "prompt"');
|
|
424
|
+
}
|
|
425
|
+
});
|
|
390
426
|
program.parse(process.argv);
|
|
391
427
|
const opts = program.opts();
|
|
392
428
|
const promptArgs = program.args;
|
|
@@ -394,7 +430,7 @@ async function main() {
|
|
|
394
430
|
if (opts.quiet)
|
|
395
431
|
setQuiet(true);
|
|
396
432
|
// If a sub-command was run, we're done
|
|
397
|
-
if (['byok', 'auth', 'ide', 'ollama', 'openclaw', 'pull', 'doctor'].includes(program.args[0]))
|
|
433
|
+
if (['byok', 'auth', 'ide', 'ollama', 'openclaw', 'pull', 'doctor', 'serve', 'agents'].includes(program.args[0]))
|
|
398
434
|
return;
|
|
399
435
|
// Check for API key (BYOK or local provider)
|
|
400
436
|
let byokActive = isByokEnabled();
|
|
@@ -408,9 +444,10 @@ async function main() {
|
|
|
408
444
|
localActive = isLocalProvider(envDetected);
|
|
409
445
|
printSuccess(`Auto-detected ${PROVIDERS[envDetected].name} from environment.`);
|
|
410
446
|
}
|
|
411
|
-
// Priority 2: Check local providers in PARALLEL (
|
|
447
|
+
// Priority 2: Check local providers in PARALLEL (all at once, use whichever responds first)
|
|
412
448
|
if (!byokActive) {
|
|
413
|
-
const
|
|
449
|
+
const { isLmStudioRunning, isJanRunning, setupLmStudio, setupJan } = await import('./auth.js');
|
|
450
|
+
const [ollamaResult, lmstudioResult, janResult, openclawResult] = await Promise.allSettled([
|
|
414
451
|
// Check Ollama
|
|
415
452
|
(async () => {
|
|
416
453
|
const up = await isOllamaRunning();
|
|
@@ -422,6 +459,22 @@ async function main() {
|
|
|
422
459
|
const ok = await setupOllama();
|
|
423
460
|
return ok ? { provider: 'ollama', models: models.length } : null;
|
|
424
461
|
})(),
|
|
462
|
+
// Check LM Studio
|
|
463
|
+
(async () => {
|
|
464
|
+
const up = await isLmStudioRunning();
|
|
465
|
+
if (!up)
|
|
466
|
+
return null;
|
|
467
|
+
const ok = await setupLmStudio();
|
|
468
|
+
return ok ? { provider: 'lmstudio' } : null;
|
|
469
|
+
})(),
|
|
470
|
+
// Check Jan
|
|
471
|
+
(async () => {
|
|
472
|
+
const up = await isJanRunning();
|
|
473
|
+
if (!up)
|
|
474
|
+
return null;
|
|
475
|
+
const ok = await setupJan();
|
|
476
|
+
return ok ? { provider: 'jan' } : null;
|
|
477
|
+
})(),
|
|
425
478
|
// Check OpenClaw
|
|
426
479
|
(async () => {
|
|
427
480
|
try {
|
|
@@ -436,14 +489,26 @@ async function main() {
|
|
|
436
489
|
}
|
|
437
490
|
})(),
|
|
438
491
|
]);
|
|
439
|
-
// Prefer Ollama
|
|
492
|
+
// Prefer Ollama > LM Studio > Jan > OpenClaw
|
|
440
493
|
const ollamaOk = ollamaResult.status === 'fulfilled' && ollamaResult.value;
|
|
494
|
+
const lmstudioOk = lmstudioResult.status === 'fulfilled' && lmstudioResult.value;
|
|
495
|
+
const janOk = janResult.status === 'fulfilled' && janResult.value;
|
|
441
496
|
const openclawOk = openclawResult.status === 'fulfilled' && openclawResult.value;
|
|
442
497
|
if (ollamaOk) {
|
|
443
498
|
byokActive = true;
|
|
444
499
|
localActive = true;
|
|
445
500
|
printSuccess(`Auto-configured Ollama (${ollamaOk.models} models). Ready — $0 cost!`);
|
|
446
501
|
}
|
|
502
|
+
else if (lmstudioOk) {
|
|
503
|
+
byokActive = true;
|
|
504
|
+
localActive = true;
|
|
505
|
+
printSuccess('Auto-configured LM Studio. Ready — $0 cost!');
|
|
506
|
+
}
|
|
507
|
+
else if (janOk) {
|
|
508
|
+
byokActive = true;
|
|
509
|
+
localActive = true;
|
|
510
|
+
printSuccess('Auto-configured Jan. Ready — $0 cost!');
|
|
511
|
+
}
|
|
447
512
|
else if (openclawOk) {
|
|
448
513
|
byokActive = true;
|
|
449
514
|
localActive = true;
|
|
@@ -474,6 +539,9 @@ async function main() {
|
|
|
474
539
|
{ env: 'PERPLEXITY_API_KEY', provider: 'perplexity' },
|
|
475
540
|
{ env: 'COHERE_API_KEY', provider: 'cohere' },
|
|
476
541
|
{ env: 'NVIDIA_API_KEY', provider: 'nvidia' },
|
|
542
|
+
{ env: 'SAMBANOVA_API_KEY', provider: 'sambanova' },
|
|
543
|
+
{ env: 'CEREBRAS_API_KEY', provider: 'cerebras' },
|
|
544
|
+
{ env: 'OPENROUTER_API_KEY', provider: 'openrouter' },
|
|
477
545
|
];
|
|
478
546
|
for (const { env, provider } of envKeys) {
|
|
479
547
|
if (process.env[env])
|
|
@@ -499,6 +567,8 @@ async function main() {
|
|
|
499
567
|
setPermissionMode('permissive');
|
|
500
568
|
}
|
|
501
569
|
}
|
|
570
|
+
// Register built-in agents (hacker, operator, dreamer) so --agent flag works
|
|
571
|
+
registerBuiltinAgents();
|
|
502
572
|
// Parallel startup: register tools, gather context, check updates, and cloud sync
|
|
503
573
|
const [, context, , syncMsg] = await Promise.all([
|
|
504
574
|
registerAllTools({ computerUse: opts.computerUse }),
|
|
@@ -528,6 +598,11 @@ async function main() {
|
|
|
528
598
|
thinking: opts.thinking || false,
|
|
529
599
|
thinkingBudget: opts.thinkingBudget ? (parseInt(opts.thinkingBudget, 10) || 10000) : undefined,
|
|
530
600
|
};
|
|
601
|
+
// Enable self-evaluation if requested
|
|
602
|
+
if (opts.selfEval) {
|
|
603
|
+
const { setSelfEvalEnabled } = await import('./self-eval.js');
|
|
604
|
+
setSelfEvalEnabled(true);
|
|
605
|
+
}
|
|
531
606
|
// Pipe mode: echo "prompt" | kbot -p OR kbot -p "prompt"
|
|
532
607
|
if (opts.pipe) {
|
|
533
608
|
let message = promptArgs.join(' ');
|
|
@@ -725,12 +800,13 @@ async function byokFlow() {
|
|
|
725
800
|
async function guidedSetup() {
|
|
726
801
|
console.log(banner(VERSION));
|
|
727
802
|
console.log();
|
|
728
|
-
console.log(chalk.bold('
|
|
803
|
+
console.log(chalk.bold(' Hey! I\'m K:BOT — your AI assistant for the terminal.'));
|
|
729
804
|
console.log();
|
|
730
|
-
console.log(chalk.dim('
|
|
805
|
+
console.log(chalk.dim(' I can write code, answer questions, search the web, manage git,'));
|
|
806
|
+
console.log(chalk.dim(' and a lot more. First, I need an AI brain. Pick one:'));
|
|
731
807
|
console.log();
|
|
732
|
-
console.log(` ${chalk.bold('1.')} ${chalk.hex('#6B8E6B')('Free & Private')} — Run AI on your computer (no account
|
|
733
|
-
console.log(` ${chalk.bold('2.')} ${chalk.hex('#5B8BA0')('Cloud AI')} — Use an API key
|
|
808
|
+
console.log(` ${chalk.bold('1.')} ${chalk.hex('#6B8E6B')('Free & Private')} — Run AI on your computer (no account, no cost)`);
|
|
809
|
+
console.log(` ${chalk.bold('2.')} ${chalk.hex('#5B8BA0')('Cloud AI')} — Use an API key (OpenAI, Google, Anthropic, etc.)`);
|
|
734
810
|
console.log();
|
|
735
811
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
736
812
|
const choice = await new Promise((resolve) => {
|
|
@@ -871,14 +947,48 @@ async function startRepl(agentOpts, context, tier, byokActive = false, localActi
|
|
|
871
947
|
printInfo(`${p.name}`);
|
|
872
948
|
}
|
|
873
949
|
const sessionCount = incrementSessions();
|
|
950
|
+
// Return-visit greeting — show kbot's growth
|
|
951
|
+
if (sessionCount > 1) {
|
|
952
|
+
const stats = getExtendedStats();
|
|
953
|
+
const parts = [];
|
|
954
|
+
if (stats.patternsCount > 0)
|
|
955
|
+
parts.push(`${stats.patternsCount} patterns learned`);
|
|
956
|
+
if (stats.solutionsCount > 0)
|
|
957
|
+
parts.push(`${stats.solutionsCount} solutions cached`);
|
|
958
|
+
if (stats.knowledgeCount > 0)
|
|
959
|
+
parts.push(`${stats.knowledgeCount} facts remembered`);
|
|
960
|
+
if (parts.length > 0) {
|
|
961
|
+
printInfo(`Session ${stats.sessions} · ${parts.join(' · ')}`);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
874
964
|
const rl = createInterface({
|
|
875
965
|
input: process.stdin,
|
|
876
966
|
output: process.stdout,
|
|
877
967
|
prompt: kbotPrompt(),
|
|
878
968
|
});
|
|
879
|
-
// First time? Show a
|
|
969
|
+
// First time? Show a friendly walkthrough
|
|
880
970
|
if (sessionCount <= 1) {
|
|
881
|
-
|
|
971
|
+
console.log();
|
|
972
|
+
console.log(chalk.dim(' ┌─────────────────────────────────────────────┐'));
|
|
973
|
+
console.log(chalk.dim(' │') + chalk.bold(' Welcome! Here are some things you can try: ') + chalk.dim(' │'));
|
|
974
|
+
console.log(chalk.dim(' │ │'));
|
|
975
|
+
console.log(chalk.dim(' │') + ' "explain this project" ' + chalk.dim(' │'));
|
|
976
|
+
console.log(chalk.dim(' │') + ' "write a function that sorts names" ' + chalk.dim(' │'));
|
|
977
|
+
console.log(chalk.dim(' │') + ' "find all TODO comments in this repo" ' + chalk.dim(' │'));
|
|
978
|
+
console.log(chalk.dim(' │') + ' "what files are in this directory?" ' + chalk.dim(' │'));
|
|
979
|
+
console.log(chalk.dim(' │ │'));
|
|
980
|
+
console.log(chalk.dim(' │') + chalk.dim(' Type /help for more commands. ') + chalk.dim(' │'));
|
|
981
|
+
console.log(chalk.dim(' └─────────────────────────────────────────────┘'));
|
|
982
|
+
console.log();
|
|
983
|
+
}
|
|
984
|
+
else if (sessionCount <= 3) {
|
|
985
|
+
// Second and third time — show a quick tip they might not know
|
|
986
|
+
const tips = [
|
|
987
|
+
'Tip: kbot picks the right specialist for you. Try asking about science, code, or writing.',
|
|
988
|
+
'Tip: Type /save to keep this conversation. /resume to pick it up later.',
|
|
989
|
+
'Tip: kbot learns from you. The more you use it, the better it gets.',
|
|
990
|
+
];
|
|
991
|
+
printInfo(tips[Math.min(sessionCount - 1, tips.length - 1)]);
|
|
882
992
|
}
|
|
883
993
|
console.log();
|
|
884
994
|
rl.prompt();
|
|
@@ -915,12 +1025,28 @@ async function startRepl(agentOpts, context, tier, byokActive = false, localActi
|
|
|
915
1025
|
if (!response.streamed) {
|
|
916
1026
|
printResponse(response.agent, response.content);
|
|
917
1027
|
}
|
|
918
|
-
//
|
|
919
|
-
|
|
920
|
-
const
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
1028
|
+
// Mentor footer — teach the user what kbot did (agent, tools, cost)
|
|
1029
|
+
{
|
|
1030
|
+
const parts = [];
|
|
1031
|
+
// Show which agent handled it (teaches routing)
|
|
1032
|
+
if (response.agent && response.agent !== 'kernel') {
|
|
1033
|
+
parts.push(`${response.agent} agent`);
|
|
1034
|
+
}
|
|
1035
|
+
if (response.toolCalls > 0) {
|
|
1036
|
+
parts.push(`${response.toolCalls} tool${response.toolCalls > 1 ? 's' : ''} used`);
|
|
1037
|
+
}
|
|
1038
|
+
if (response.usage) {
|
|
1039
|
+
const tokens = response.usage.input_tokens + response.usage.output_tokens;
|
|
1040
|
+
const cost = response.usage.cost_usd === 0 ? 'free' : `$${response.usage.cost_usd.toFixed(4)}`;
|
|
1041
|
+
parts.push(`${tokens} tokens · ${cost}`);
|
|
1042
|
+
}
|
|
1043
|
+
if (parts.length > 0) {
|
|
1044
|
+
printInfo(parts.join(' · '));
|
|
1045
|
+
}
|
|
1046
|
+
// On first 5 sessions, teach what just happened
|
|
1047
|
+
if (sessionCount <= 5 && response.agent && response.agent !== 'kernel') {
|
|
1048
|
+
printInfo(chalk.dim(` I picked the ${response.agent} agent for this. You can also say /agent ${response.agent} to use it directly.`));
|
|
1049
|
+
}
|
|
924
1050
|
}
|
|
925
1051
|
// Schedule cloud sync push (debounced — batches writes)
|
|
926
1052
|
schedulePush();
|
|
@@ -1057,6 +1183,47 @@ async function handleSlashCommand(input, opts, rl) {
|
|
|
1057
1183
|
case 'help':
|
|
1058
1184
|
printHelp();
|
|
1059
1185
|
break;
|
|
1186
|
+
case 'tutorial': {
|
|
1187
|
+
console.log();
|
|
1188
|
+
console.log(chalk.bold(' Let\'s build something together. Pick a track:'));
|
|
1189
|
+
console.log();
|
|
1190
|
+
console.log(` ${chalk.bold('1.')} ${chalk.hex('#4ADE80')('Build a website')} — Create an HTML page from scratch`);
|
|
1191
|
+
console.log(` ${chalk.bold('2.')} ${chalk.hex('#60A5FA')('Fix a bug')} — Find and fix a problem in code`);
|
|
1192
|
+
console.log(` ${chalk.bold('3.')} ${chalk.hex('#FB923C')('Write a script')} — Automate something with Python or JavaScript`);
|
|
1193
|
+
console.log(` ${chalk.bold('4.')} ${chalk.hex('#F472B6')('Research a topic')} — Deep-dive into any subject`);
|
|
1194
|
+
console.log(` ${chalk.bold('5.')} ${chalk.hex('#A78BFA')('Explore this project')} — Understand the code in this folder`);
|
|
1195
|
+
console.log();
|
|
1196
|
+
console.log(chalk.dim(' Pick a number, or just type what you want to build.'));
|
|
1197
|
+
console.log();
|
|
1198
|
+
const tutorialInput = await new Promise((resolve) => {
|
|
1199
|
+
rl.question(' Your choice: ', (answer) => resolve(answer.trim()));
|
|
1200
|
+
});
|
|
1201
|
+
const tutorialPrompts = {
|
|
1202
|
+
'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.',
|
|
1203
|
+
'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.',
|
|
1204
|
+
'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.',
|
|
1205
|
+
'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.',
|
|
1206
|
+
'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.',
|
|
1207
|
+
};
|
|
1208
|
+
const prompt = tutorialPrompts[tutorialInput] || tutorialInput;
|
|
1209
|
+
if (prompt) {
|
|
1210
|
+
console.log();
|
|
1211
|
+
printInfo('Great choice! Let me work on that...');
|
|
1212
|
+
console.log();
|
|
1213
|
+
try {
|
|
1214
|
+
const response = await runAgent(prompt, opts);
|
|
1215
|
+
if (!response.streamed) {
|
|
1216
|
+
printResponse(response.agent, response.content);
|
|
1217
|
+
}
|
|
1218
|
+
console.log();
|
|
1219
|
+
printInfo(chalk.dim('That\'s the basics! Keep asking questions — I learn from every conversation.'));
|
|
1220
|
+
}
|
|
1221
|
+
catch (err) {
|
|
1222
|
+
printError(err instanceof Error ? err.message : String(err));
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
break;
|
|
1226
|
+
}
|
|
1060
1227
|
case 'agent':
|
|
1061
1228
|
if (args[0]) {
|
|
1062
1229
|
opts.agent = args[0];
|
|
@@ -1227,6 +1394,37 @@ async function handleSlashCommand(input, opts, rl) {
|
|
|
1227
1394
|
if (opts.thinking)
|
|
1228
1395
|
printInfo('AI will show reasoning steps before responding.');
|
|
1229
1396
|
break;
|
|
1397
|
+
case 'self-eval':
|
|
1398
|
+
case 'selfeval': {
|
|
1399
|
+
const { isSelfEvalEnabled, setSelfEvalEnabled } = await import('./self-eval.js');
|
|
1400
|
+
const newState = !isSelfEvalEnabled();
|
|
1401
|
+
setSelfEvalEnabled(newState);
|
|
1402
|
+
printSuccess(`Self-evaluation: ${newState ? 'ON' : 'OFF'}`);
|
|
1403
|
+
if (newState)
|
|
1404
|
+
printInfo('Responses will be scored for quality and retried if below threshold.');
|
|
1405
|
+
break;
|
|
1406
|
+
}
|
|
1407
|
+
case 'health':
|
|
1408
|
+
case 'providers': {
|
|
1409
|
+
const { getProviderHealth } = await import('./provider-fallback.js');
|
|
1410
|
+
const health = getProviderHealth();
|
|
1411
|
+
const active = health.filter(h => h.lastSuccess || h.lastFailure);
|
|
1412
|
+
if (active.length === 0) {
|
|
1413
|
+
printInfo('No provider calls recorded yet.');
|
|
1414
|
+
}
|
|
1415
|
+
else {
|
|
1416
|
+
console.log();
|
|
1417
|
+
printInfo('Provider Health:');
|
|
1418
|
+
for (const h of active) {
|
|
1419
|
+
const status = h.isHealthy ? chalk.green('healthy') : chalk.red('unhealthy');
|
|
1420
|
+
const latency = h.avgLatencyMs ? `${h.avgLatencyMs}ms` : '-';
|
|
1421
|
+
const failures = h.consecutiveFailures > 0 ? chalk.yellow(` (${h.consecutiveFailures} failures)`) : '';
|
|
1422
|
+
printInfo(` ${h.provider}: ${status} · ${latency}${failures}`);
|
|
1423
|
+
}
|
|
1424
|
+
console.log();
|
|
1425
|
+
}
|
|
1426
|
+
break;
|
|
1427
|
+
}
|
|
1230
1428
|
case 'plan': {
|
|
1231
1429
|
const planTask = args.join(' ');
|
|
1232
1430
|
if (!planTask) {
|
|
@@ -1499,7 +1697,8 @@ async function handleSlashCommand(input, opts, rl) {
|
|
|
1499
1697
|
rl.close();
|
|
1500
1698
|
break;
|
|
1501
1699
|
default:
|
|
1502
|
-
printError(`
|
|
1700
|
+
printError(`I don't know "/${cmd}". Here are some you can try:`);
|
|
1701
|
+
printInfo(' /save — save this chat | /agent — pick a specialist | /help — see everything');
|
|
1503
1702
|
}
|
|
1504
1703
|
}
|
|
1505
1704
|
// Prevent unhandled rejections from killing the process
|