@kernel.chat/kbot 3.9.0 → 3.11.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/a2a-client.d.ts +162 -0
- package/dist/a2a-client.d.ts.map +1 -0
- package/dist/a2a-client.js +376 -0
- package/dist/a2a-client.js.map +1 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +96 -5
- package/dist/agent.js.map +1 -1
- package/dist/cli.js +295 -3
- package/dist/cli.js.map +1 -1
- package/dist/mcp-apps.d.ts +90 -0
- package/dist/mcp-apps.d.ts.map +1 -0
- package/dist/mcp-apps.js +497 -0
- package/dist/mcp-apps.js.map +1 -0
- package/dist/memory-synthesis.d.ts +67 -0
- package/dist/memory-synthesis.d.ts.map +1 -0
- package/dist/memory-synthesis.js +557 -0
- package/dist/memory-synthesis.js.map +1 -0
- package/dist/prompt-evolution.d.ts +92 -0
- package/dist/prompt-evolution.d.ts.map +1 -0
- package/dist/prompt-evolution.js +371 -0
- package/dist/prompt-evolution.js.map +1 -0
- package/dist/reflection.d.ts +33 -0
- package/dist/reflection.d.ts.map +1 -0
- package/dist/reflection.js +368 -0
- package/dist/reflection.js.map +1 -0
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +56 -6
- package/dist/serve.js.map +1 -1
- package/dist/skill-library.d.ts +60 -0
- package/dist/skill-library.d.ts.map +1 -0
- package/dist/skill-library.js +475 -0
- package/dist/skill-library.js.map +1 -0
- package/dist/spec.d.ts +23 -0
- package/dist/spec.d.ts.map +1 -0
- package/dist/spec.js +177 -0
- package/dist/spec.js.map +1 -0
- package/dist/tool-pipeline.d.ts +7 -0
- package/dist/tool-pipeline.d.ts.map +1 -1
- package/dist/tool-pipeline.js +32 -0
- package/dist/tool-pipeline.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +2 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tree-planner.d.ts +63 -0
- package/dist/tree-planner.d.ts.map +1 -0
- package/dist/tree-planner.js +818 -0
- package/dist/tree-planner.js.map +1 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -20,6 +20,7 @@ import { clearHistory, clearMemory, compactHistory, restoreHistory } from './mem
|
|
|
20
20
|
import { saveSession, loadSession, listSessions, deleteSession, formatSessionList, } from './sessions.js';
|
|
21
21
|
import { createAgent, removeAgent, getAgent, formatAgentList, formatAgentDetail, PRESETS, getMatrixAgentIds, activateMimic, listMimicProfiles, getMimicProfile, registerBuiltinAgents, formatBuiltinAgentList, formatBuiltinAgentDetail, } from './matrix.js';
|
|
22
22
|
import { getExtendedStats, incrementSessions, learnFact, selfTrain, getTrainingLog, flushPendingWrites } from './learning.js';
|
|
23
|
+
import { maybeSynthesize, getSynthesisStats } from './memory-synthesis.js';
|
|
23
24
|
import { banner, bannerCompact, bannerAuth, prompt as kbotPrompt, printError, printSuccess, printInfo, printWarn, printResponse, printHelp, printGoodbye, setQuiet, } from './ui.js';
|
|
24
25
|
import { checkForUpdate, selfUpdate } from './updater.js';
|
|
25
26
|
import { runTutorial } from './tutorial.js';
|
|
@@ -48,6 +49,7 @@ async function main() {
|
|
|
48
49
|
.option('--self-eval', 'Enable self-evaluation loop (score and retry low-quality responses)')
|
|
49
50
|
.option('--plan', 'Plan mode — read-only exploration, no changes')
|
|
50
51
|
.option('--architect', 'Architect mode — plan-review-implement with dual agents')
|
|
52
|
+
.option('--tree', 'Tree planning mode — LATS branching search instead of linear plans')
|
|
51
53
|
.option('--safe', 'Confirm destructive operations')
|
|
52
54
|
.option('--strict', 'Confirm ALL operations')
|
|
53
55
|
.argument('[prompt...]', 'One-shot prompt')
|
|
@@ -1024,6 +1026,250 @@ async function main() {
|
|
|
1024
1026
|
computerUse: opts.computerUse,
|
|
1025
1027
|
});
|
|
1026
1028
|
});
|
|
1029
|
+
program
|
|
1030
|
+
.command('apps [tool]')
|
|
1031
|
+
.description('MCP Apps — list app-capable tools, or run one and render its HTML output')
|
|
1032
|
+
.option('--render', 'Run the tool and render its MCP App output in the browser')
|
|
1033
|
+
.option('--inline', 'Return inline HTML instead of opening browser')
|
|
1034
|
+
.option('--args <json>', 'JSON arguments for the tool (use with --render)')
|
|
1035
|
+
.action(async (tool, opts) => {
|
|
1036
|
+
const { registerMcpAppTools, listAppCapableTools, getAppConfig, renderMcpApp, extractMcpAppFromText } = await import('./mcp-apps.js');
|
|
1037
|
+
const { ensureLazyToolsLoaded, executeTool: execTool } = await import('./tools/index.js');
|
|
1038
|
+
// Ensure tools are loaded (including MCP App tools)
|
|
1039
|
+
await ensureLazyToolsLoaded();
|
|
1040
|
+
if (!tool) {
|
|
1041
|
+
// List all app-capable tools
|
|
1042
|
+
const appTools = listAppCapableTools();
|
|
1043
|
+
if (appTools.length === 0) {
|
|
1044
|
+
printInfo('No MCP App-capable tools registered.');
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
process.stderr.write(`\n ${chalk.hex('#6B5B95')('MCP App Tools')} (${appTools.length}):\n\n`);
|
|
1048
|
+
for (const t of appTools) {
|
|
1049
|
+
process.stderr.write(` ${chalk.bold(t.name)} — ${t.description}\n`);
|
|
1050
|
+
}
|
|
1051
|
+
process.stderr.write(`\n ${chalk.dim('Run a tool:')} kbot apps --render <tool> --args \'{"key":"value"}\'\n`);
|
|
1052
|
+
process.stderr.write(` ${chalk.dim('Config:')} ~/.kbot/config.json → mcpApps.renderMode (browser|inline|disabled)\n\n`);
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
if (opts?.render) {
|
|
1056
|
+
// Parse args
|
|
1057
|
+
let toolArgs = {};
|
|
1058
|
+
if (opts.args) {
|
|
1059
|
+
try {
|
|
1060
|
+
toolArgs = JSON.parse(opts.args);
|
|
1061
|
+
}
|
|
1062
|
+
catch {
|
|
1063
|
+
printError('Invalid JSON for --args. Example: --args \'{"type":"bar","labels":["A","B"],"datasets":[{"data":[1,2]}]}\'');
|
|
1064
|
+
return;
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
// Execute the tool
|
|
1068
|
+
printInfo(`Running ${tool}...`);
|
|
1069
|
+
const result = await execTool({
|
|
1070
|
+
id: `apps_${Date.now()}`,
|
|
1071
|
+
name: tool,
|
|
1072
|
+
arguments: toolArgs,
|
|
1073
|
+
});
|
|
1074
|
+
if (result.error) {
|
|
1075
|
+
printError(`Tool error: ${result.result}`);
|
|
1076
|
+
return;
|
|
1077
|
+
}
|
|
1078
|
+
// Try to extract MCP App from result
|
|
1079
|
+
const appResult = extractMcpAppFromText(result.result);
|
|
1080
|
+
if (!appResult) {
|
|
1081
|
+
printWarn(`Tool "${tool}" did not return MCP App content. Text output:`);
|
|
1082
|
+
console.log(result.result);
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
1085
|
+
// Render the app
|
|
1086
|
+
const config = getAppConfig();
|
|
1087
|
+
if (opts.inline) {
|
|
1088
|
+
config.renderMode = 'inline';
|
|
1089
|
+
}
|
|
1090
|
+
const rendered = await renderMcpApp(appResult, config);
|
|
1091
|
+
printSuccess(`MCP App: ${appResult.title ?? tool}`);
|
|
1092
|
+
if (rendered.path) {
|
|
1093
|
+
printInfo(`Opened in browser: ${rendered.path}`);
|
|
1094
|
+
}
|
|
1095
|
+
if (rendered.rendered && opts.inline) {
|
|
1096
|
+
console.log(rendered.rendered);
|
|
1097
|
+
}
|
|
1098
|
+
console.log(rendered.text);
|
|
1099
|
+
}
|
|
1100
|
+
else {
|
|
1101
|
+
// Show info about the specific tool
|
|
1102
|
+
const appTools = listAppCapableTools();
|
|
1103
|
+
const match = appTools.find(t => t.name === tool);
|
|
1104
|
+
if (match) {
|
|
1105
|
+
printInfo(`${match.name} — ${match.description}`);
|
|
1106
|
+
printInfo(`\nRun with: kbot apps --render ${match.name} --args '{...}'`);
|
|
1107
|
+
}
|
|
1108
|
+
else {
|
|
1109
|
+
printError(`Tool "${tool}" is not registered as MCP App-capable.`);
|
|
1110
|
+
printInfo('Run `kbot apps` to see available tools.');
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
});
|
|
1114
|
+
// ── A2A (Agent-to-Agent) subcommands ──
|
|
1115
|
+
const a2aCmd = program
|
|
1116
|
+
.command('a2a')
|
|
1117
|
+
.description('Agent-to-Agent protocol — discover agents, send tasks, collaborate');
|
|
1118
|
+
a2aCmd
|
|
1119
|
+
.command('card')
|
|
1120
|
+
.description('Print this kbot instance\'s Agent Card JSON')
|
|
1121
|
+
.option('--url <url>', 'Override the endpoint URL in the card')
|
|
1122
|
+
.action(async (opts) => {
|
|
1123
|
+
const { generateAgentCard } = await import('./a2a-client.js');
|
|
1124
|
+
const card = generateAgentCard(opts.url);
|
|
1125
|
+
console.log(JSON.stringify(card, null, 2));
|
|
1126
|
+
});
|
|
1127
|
+
a2aCmd
|
|
1128
|
+
.command('discover <url>')
|
|
1129
|
+
.description('Discover a remote A2A agent at the given URL')
|
|
1130
|
+
.action(async (url) => {
|
|
1131
|
+
const { discoverAgent } = await import('./a2a-client.js');
|
|
1132
|
+
printInfo(`Discovering agent at ${url}...`);
|
|
1133
|
+
const card = await discoverAgent(url);
|
|
1134
|
+
if (!card) {
|
|
1135
|
+
printError(`No A2A agent found at ${url}`);
|
|
1136
|
+
printInfo('Make sure the agent serves /.well-known/agent.json');
|
|
1137
|
+
process.exit(1);
|
|
1138
|
+
}
|
|
1139
|
+
printSuccess(`Discovered: ${card.name} (v${card.version})`);
|
|
1140
|
+
printInfo(` ${card.description}`);
|
|
1141
|
+
printInfo(` Skills: ${card.skills.length}`);
|
|
1142
|
+
for (const skill of card.skills) {
|
|
1143
|
+
printInfo(` • ${skill.name} — ${skill.description}`);
|
|
1144
|
+
}
|
|
1145
|
+
printInfo(` Streaming: ${card.capabilities.streaming}`);
|
|
1146
|
+
printInfo(` Agent saved to local registry.`);
|
|
1147
|
+
});
|
|
1148
|
+
a2aCmd
|
|
1149
|
+
.command('send <url> <prompt...>')
|
|
1150
|
+
.description('Send a task to a remote A2A agent')
|
|
1151
|
+
.option('--agent <agent>', 'Hint which specialist should handle the task')
|
|
1152
|
+
.option('--token <token>', 'Auth token for the remote agent')
|
|
1153
|
+
.option('--async', 'Submit asynchronously (don\'t wait for completion)')
|
|
1154
|
+
.action(async (url, promptParts, opts) => {
|
|
1155
|
+
const { sendTask } = await import('./a2a-client.js');
|
|
1156
|
+
const prompt = promptParts.join(' ');
|
|
1157
|
+
const sync = !opts.async;
|
|
1158
|
+
printInfo(`Sending task to ${url}${sync ? ' (waiting for result)' : ' (async)'}...`);
|
|
1159
|
+
try {
|
|
1160
|
+
const result = await sendTask(url, prompt, {
|
|
1161
|
+
agent: opts.agent,
|
|
1162
|
+
token: opts.token,
|
|
1163
|
+
sync,
|
|
1164
|
+
});
|
|
1165
|
+
if (result.status === 'completed' && result.text) {
|
|
1166
|
+
printSuccess(`Task ${result.id} completed`);
|
|
1167
|
+
console.log();
|
|
1168
|
+
console.log(result.text);
|
|
1169
|
+
}
|
|
1170
|
+
else if (result.status === 'submitted') {
|
|
1171
|
+
printInfo(`Task submitted: ${result.id}`);
|
|
1172
|
+
printInfo(`Check status: kbot a2a status ${url} ${result.id}`);
|
|
1173
|
+
}
|
|
1174
|
+
else {
|
|
1175
|
+
printWarn(`Task ${result.id} — status: ${result.status}`);
|
|
1176
|
+
if (result.text)
|
|
1177
|
+
console.log(result.text);
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
catch (err) {
|
|
1181
|
+
printError(`Task failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1182
|
+
process.exit(1);
|
|
1183
|
+
}
|
|
1184
|
+
});
|
|
1185
|
+
a2aCmd
|
|
1186
|
+
.command('status <url> <taskId>')
|
|
1187
|
+
.description('Check the status of a task on a remote agent')
|
|
1188
|
+
.option('--token <token>', 'Auth token for the remote agent')
|
|
1189
|
+
.action(async (url, taskId, opts) => {
|
|
1190
|
+
const { getTaskStatus } = await import('./a2a-client.js');
|
|
1191
|
+
try {
|
|
1192
|
+
const result = await getTaskStatus(url, taskId, { token: opts.token });
|
|
1193
|
+
printInfo(`Task ${result.id}: ${result.status}`);
|
|
1194
|
+
if (result.message)
|
|
1195
|
+
printInfo(` Message: ${result.message}`);
|
|
1196
|
+
if (result.text) {
|
|
1197
|
+
console.log();
|
|
1198
|
+
console.log(result.text);
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
catch (err) {
|
|
1202
|
+
printError(`Status check failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1203
|
+
process.exit(1);
|
|
1204
|
+
}
|
|
1205
|
+
});
|
|
1206
|
+
a2aCmd
|
|
1207
|
+
.command('cancel <url> <taskId>')
|
|
1208
|
+
.description('Cancel a running task on a remote agent')
|
|
1209
|
+
.option('--token <token>', 'Auth token for the remote agent')
|
|
1210
|
+
.action(async (url, taskId, opts) => {
|
|
1211
|
+
const { cancelTask } = await import('./a2a-client.js');
|
|
1212
|
+
try {
|
|
1213
|
+
const canceled = await cancelTask(url, taskId, { token: opts.token });
|
|
1214
|
+
if (canceled) {
|
|
1215
|
+
printSuccess(`Task ${taskId} canceled.`);
|
|
1216
|
+
}
|
|
1217
|
+
else {
|
|
1218
|
+
printWarn(`Task ${taskId} is already in a terminal state (completed or failed).`);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
catch (err) {
|
|
1222
|
+
printError(`Cancel failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1223
|
+
process.exit(1);
|
|
1224
|
+
}
|
|
1225
|
+
});
|
|
1226
|
+
a2aCmd
|
|
1227
|
+
.command('agents')
|
|
1228
|
+
.description('List all discovered remote agents in the local registry')
|
|
1229
|
+
.action(async () => {
|
|
1230
|
+
const { listRemoteAgents, removeRemoteAgent } = await import('./a2a-client.js');
|
|
1231
|
+
const agents = listRemoteAgents();
|
|
1232
|
+
if (agents.length === 0) {
|
|
1233
|
+
printInfo('No remote agents discovered yet.');
|
|
1234
|
+
printInfo('Discover one: kbot a2a discover <url>');
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
printInfo(`${agents.length} discovered agent${agents.length === 1 ? '' : 's'}:`);
|
|
1238
|
+
for (const agent of agents) {
|
|
1239
|
+
printInfo(` • ${agent.card.name} (v${agent.card.version})`);
|
|
1240
|
+
printInfo(` URL: ${agent.url}`);
|
|
1241
|
+
printInfo(` Skills: ${agent.card.skills.length}`);
|
|
1242
|
+
printInfo(` Discovered: ${agent.discoveredAt}`);
|
|
1243
|
+
if (agent.lastContactedAt) {
|
|
1244
|
+
printInfo(` Last contact: ${agent.lastContactedAt}`);
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
});
|
|
1248
|
+
a2aCmd
|
|
1249
|
+
.command('history')
|
|
1250
|
+
.description('Show local task history (tasks sent to remote agents)')
|
|
1251
|
+
.option('--clear', 'Clear the task history')
|
|
1252
|
+
.action(async (opts) => {
|
|
1253
|
+
const { getTaskHistory, clearTaskHistory } = await import('./a2a-client.js');
|
|
1254
|
+
if (opts.clear) {
|
|
1255
|
+
clearTaskHistory();
|
|
1256
|
+
printSuccess('Task history cleared.');
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1259
|
+
const history = getTaskHistory();
|
|
1260
|
+
if (history.length === 0) {
|
|
1261
|
+
printInfo('No task history yet.');
|
|
1262
|
+
return;
|
|
1263
|
+
}
|
|
1264
|
+
printInfo(`${history.length} task${history.length === 1 ? '' : 's'} in history:`);
|
|
1265
|
+
for (const entry of history.slice(-20).reverse()) {
|
|
1266
|
+
const status = entry.status === 'completed' ? chalk.green(entry.status)
|
|
1267
|
+
: entry.status === 'failed' ? chalk.red(entry.status)
|
|
1268
|
+
: chalk.yellow(entry.status);
|
|
1269
|
+
printInfo(` ${entry.id.slice(0, 8)} ${status} ${entry.agentUrl}`);
|
|
1270
|
+
printInfo(` ${chalk.dim(entry.prompt.slice(0, 80))}`);
|
|
1271
|
+
}
|
|
1272
|
+
});
|
|
1027
1273
|
program
|
|
1028
1274
|
.command('kbot-local')
|
|
1029
1275
|
.description('Use kbot local gateway as AI provider')
|
|
@@ -1406,6 +1652,33 @@ async function main() {
|
|
|
1406
1652
|
await new Promise(() => { });
|
|
1407
1653
|
}
|
|
1408
1654
|
});
|
|
1655
|
+
program
|
|
1656
|
+
.command('spec <description>')
|
|
1657
|
+
.description('Generate a formal specification with requirements + acceptance criteria before coding')
|
|
1658
|
+
.option('--implement', 'Generate spec then pass to coder agent for implementation')
|
|
1659
|
+
.option('--agent <name>', 'Override the default architect agent', 'architect')
|
|
1660
|
+
.option('--output <path>', 'Custom output path for the spec file')
|
|
1661
|
+
.action(async (description, specOpts) => {
|
|
1662
|
+
const { generateSpec } = await import('./spec.js');
|
|
1663
|
+
const parentOpts = program.opts();
|
|
1664
|
+
try {
|
|
1665
|
+
await generateSpec(description, {
|
|
1666
|
+
agent: specOpts.agent,
|
|
1667
|
+
output: specOpts.output,
|
|
1668
|
+
implement: specOpts.implement,
|
|
1669
|
+
agentOpts: {
|
|
1670
|
+
model: parentOpts.model,
|
|
1671
|
+
stream: parentOpts.stream ?? true,
|
|
1672
|
+
thinking: parentOpts.thinking || false,
|
|
1673
|
+
thinkingBudget: parentOpts.thinkingBudget ? (parseInt(parentOpts.thinkingBudget, 10) || 10000) : undefined,
|
|
1674
|
+
},
|
|
1675
|
+
});
|
|
1676
|
+
}
|
|
1677
|
+
catch (err) {
|
|
1678
|
+
printError(err instanceof Error ? err.message : String(err));
|
|
1679
|
+
process.exit(1);
|
|
1680
|
+
}
|
|
1681
|
+
});
|
|
1409
1682
|
program
|
|
1410
1683
|
.command('completions')
|
|
1411
1684
|
.description('Generate shell tab-completion script (bash, zsh, fish)')
|
|
@@ -1426,7 +1699,7 @@ async function main() {
|
|
|
1426
1699
|
if (opts.quiet)
|
|
1427
1700
|
setQuiet(true);
|
|
1428
1701
|
// If a sub-command was run, we're done
|
|
1429
|
-
if (['byok', 'auth', 'ide', 'local', 'ollama', 'kbot-local', 'pull', 'doctor', 'serve', 'agents', 'watch', 'voice', 'export', 'plugins', 'changelog', 'completions', 'automate', 'status'].includes(program.args[0]))
|
|
1702
|
+
if (['byok', 'auth', 'ide', 'local', 'ollama', 'kbot-local', 'pull', 'doctor', 'serve', 'agents', 'watch', 'voice', 'export', 'plugins', 'changelog', 'completions', 'automate', 'status', 'spec', 'a2a'].includes(program.args[0]))
|
|
1430
1703
|
return;
|
|
1431
1704
|
// Check for API key (BYOK or local provider)
|
|
1432
1705
|
let byokActive = isByokEnabled();
|
|
@@ -1599,7 +1872,7 @@ async function main() {
|
|
|
1599
1872
|
printInfo(syncMsg);
|
|
1600
1873
|
// Determine if we're in one-shot or REPL mode
|
|
1601
1874
|
const isOneShot = promptArgs.length > 0 &&
|
|
1602
|
-
!['byok', 'auth', 'ide', 'ollama', 'kbot-local', 'pull', 'doctor'].includes(promptArgs[0]);
|
|
1875
|
+
!['byok', 'auth', 'ide', 'ollama', 'kbot-local', 'pull', 'doctor', 'spec'].includes(promptArgs[0]);
|
|
1603
1876
|
const isStdinOnly = !process.stdin.isTTY && promptArgs.length === 0;
|
|
1604
1877
|
if (isOneShot || isStdinOnly || opts.pipe) {
|
|
1605
1878
|
// One-shot / pipe mode: start lazy tools in background (non-blocking).
|
|
@@ -1740,7 +2013,7 @@ async function main() {
|
|
|
1740
2013
|
stdinContent = Buffer.concat(chunks).toString('utf-8').trim();
|
|
1741
2014
|
}
|
|
1742
2015
|
// One-shot mode: kbot "fix the bug" — always stream for speed
|
|
1743
|
-
if (promptArgs.length > 0 && !['byok', 'auth', 'ide', 'ollama', 'kbot-local', 'pull', 'doctor'].includes(promptArgs[0])) {
|
|
2016
|
+
if (promptArgs.length > 0 && !['byok', 'auth', 'ide', 'ollama', 'kbot-local', 'pull', 'doctor', 'spec'].includes(promptArgs[0])) {
|
|
1744
2017
|
if (!opts.pipe)
|
|
1745
2018
|
console.log(bannerCompact());
|
|
1746
2019
|
let message = promptArgs.join(' ');
|
|
@@ -1767,6 +2040,12 @@ async function main() {
|
|
|
1767
2040
|
await runArchitectMode(message, agentOpts);
|
|
1768
2041
|
return;
|
|
1769
2042
|
}
|
|
2043
|
+
// Tree planning mode: LATS branching search
|
|
2044
|
+
if (opts.tree) {
|
|
2045
|
+
const { executeTreePlan } = await import('./tree-planner.js');
|
|
2046
|
+
await executeTreePlan(message, agentOpts);
|
|
2047
|
+
return;
|
|
2048
|
+
}
|
|
1770
2049
|
agentOpts.stream = true; // Force streaming for faster one-shot
|
|
1771
2050
|
await runAndPrint(message, agentOpts);
|
|
1772
2051
|
return;
|
|
@@ -2089,9 +2368,20 @@ async function startRepl(agentOpts, context, tier, byokActive = false, localActi
|
|
|
2089
2368
|
printInfo(`${p.name}`);
|
|
2090
2369
|
}
|
|
2091
2370
|
const sessionCount = incrementSessions();
|
|
2371
|
+
// Three-tier memory: run synthesis on every 10th session (or first time with enough data)
|
|
2372
|
+
if (sessionCount % 10 === 0 || sessionCount === 1) {
|
|
2373
|
+
try {
|
|
2374
|
+
const insightCount = maybeSynthesize();
|
|
2375
|
+
if (insightCount > 0) {
|
|
2376
|
+
printInfo(`Memory synthesis: ${insightCount} insights generated`);
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
catch { /* synthesis is non-critical */ }
|
|
2380
|
+
}
|
|
2092
2381
|
// Return-visit greeting — show kbot's growth
|
|
2093
2382
|
if (sessionCount > 1) {
|
|
2094
2383
|
const stats = getExtendedStats();
|
|
2384
|
+
const synthStats = getSynthesisStats();
|
|
2095
2385
|
const parts = [];
|
|
2096
2386
|
if (stats.patternsCount > 0)
|
|
2097
2387
|
parts.push(`${stats.patternsCount} patterns learned`);
|
|
@@ -2099,6 +2389,8 @@ async function startRepl(agentOpts, context, tier, byokActive = false, localActi
|
|
|
2099
2389
|
parts.push(`${stats.solutionsCount} solutions cached`);
|
|
2100
2390
|
if (stats.knowledgeCount > 0)
|
|
2101
2391
|
parts.push(`${stats.knowledgeCount} facts remembered`);
|
|
2392
|
+
if (synthStats.insightCount > 0)
|
|
2393
|
+
parts.push(`${synthStats.insightCount} insights synthesized`);
|
|
2102
2394
|
if (parts.length > 0) {
|
|
2103
2395
|
printInfo(`Session ${stats.sessions} · ${parts.join(' · ')}`);
|
|
2104
2396
|
}
|