@kernel.chat/kbot 3.6.1 → 3.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/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +74 -1
- package/dist/agent.js.map +1 -1
- package/dist/bootstrap.d.ts +19 -0
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +80 -0
- package/dist/bootstrap.js.map +1 -1
- package/dist/cli.js +26 -1
- package/dist/cli.js.map +1 -1
- package/dist/skills-loader.d.ts +17 -0
- package/dist/skills-loader.d.ts.map +1 -0
- package/dist/skills-loader.js +92 -0
- package/dist/skills-loader.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Skills Loader — Auto-discover and load .md skill files
|
|
2
|
+
//
|
|
3
|
+
// Skill files are Markdown documents that inject domain knowledge, tool combinations,
|
|
4
|
+
// and project-specific patterns into the agent's context. They're the kbot equivalent
|
|
5
|
+
// of Copilot's "Agent Skills" or Cursor's "Rules for AI."
|
|
6
|
+
//
|
|
7
|
+
// Discovery locations (in priority order):
|
|
8
|
+
// 1. ./.kbot/skills/*.md — project-specific skills
|
|
9
|
+
// 2. ~/.kbot/skills/*.md — user global skills
|
|
10
|
+
//
|
|
11
|
+
// Token budget: 2000 tokens max (~8000 characters) to leave room for
|
|
12
|
+
// repo map, learning context, and memory.
|
|
13
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
14
|
+
import { join, basename } from 'node:path';
|
|
15
|
+
import { homedir } from 'node:os';
|
|
16
|
+
const MAX_SKILL_TOKENS = 2000;
|
|
17
|
+
const estimateTokens = (text) => Math.ceil(text.length / 4);
|
|
18
|
+
/**
|
|
19
|
+
* Discover and load skill files from project and global directories.
|
|
20
|
+
* Returns formatted string ready to inject into system prompt.
|
|
21
|
+
*/
|
|
22
|
+
export function loadSkills(projectRoot) {
|
|
23
|
+
const skills = discoverSkillFiles(projectRoot);
|
|
24
|
+
if (skills.length === 0)
|
|
25
|
+
return '';
|
|
26
|
+
return formatSkillsForPrompt(skills);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Discover .md files from both project-local and global skill directories.
|
|
30
|
+
* Project skills take precedence (loaded first, consume token budget first).
|
|
31
|
+
*/
|
|
32
|
+
export function discoverSkillFiles(projectRoot) {
|
|
33
|
+
const locations = [
|
|
34
|
+
join(projectRoot, '.kbot', 'skills'), // Project-specific
|
|
35
|
+
join(homedir(), '.kbot', 'skills'), // User global
|
|
36
|
+
];
|
|
37
|
+
const skills = [];
|
|
38
|
+
const seen = new Set(); // Deduplicate by filename
|
|
39
|
+
for (const dir of locations) {
|
|
40
|
+
if (!existsSync(dir))
|
|
41
|
+
continue;
|
|
42
|
+
try {
|
|
43
|
+
const files = readdirSync(dir)
|
|
44
|
+
.filter(f => f.endsWith('.md'))
|
|
45
|
+
.sort(); // Alphabetical for deterministic ordering
|
|
46
|
+
for (const file of files) {
|
|
47
|
+
if (seen.has(file))
|
|
48
|
+
continue; // Project overrides global
|
|
49
|
+
seen.add(file);
|
|
50
|
+
try {
|
|
51
|
+
const path = join(dir, file);
|
|
52
|
+
const content = readFileSync(path, 'utf-8').trim();
|
|
53
|
+
if (content.length === 0)
|
|
54
|
+
continue;
|
|
55
|
+
skills.push({
|
|
56
|
+
name: basename(file, '.md'),
|
|
57
|
+
path,
|
|
58
|
+
content,
|
|
59
|
+
tokens: estimateTokens(content),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
catch { /* permission denied, etc. */ }
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch { /* directory read error */ }
|
|
66
|
+
}
|
|
67
|
+
return skills;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Format skill files for prompt injection, respecting token budget.
|
|
71
|
+
*/
|
|
72
|
+
function formatSkillsForPrompt(skills, maxTokens = MAX_SKILL_TOKENS) {
|
|
73
|
+
const parts = [];
|
|
74
|
+
let currentTokens = 0;
|
|
75
|
+
for (const skill of skills) {
|
|
76
|
+
if (currentTokens + skill.tokens > maxTokens) {
|
|
77
|
+
// Try to fit a truncated version
|
|
78
|
+
const remaining = maxTokens - currentTokens;
|
|
79
|
+
if (remaining > 100) {
|
|
80
|
+
const truncated = skill.content.slice(0, remaining * 4) + '\n...(truncated)';
|
|
81
|
+
parts.push(`## Skill: ${skill.name}\n${truncated}`);
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
parts.push(`## Skill: ${skill.name}\n${skill.content}`);
|
|
86
|
+
currentTokens += skill.tokens;
|
|
87
|
+
}
|
|
88
|
+
if (parts.length === 0)
|
|
89
|
+
return '';
|
|
90
|
+
return `\n\n[Custom Skills]\n${parts.join('\n---\n')}`;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=skills-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-loader.js","sourceRoot":"","sources":["../src/skills-loader.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kernel.chat/kbot",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"description": "The only AI agent that builds its own tools. Self-evolving terminal AI: 290 tools, 23 agents, 20 providers. Runtime tool forging via forge_tool, Forge Registry for community tools, autopoietic health monitoring, immune self-audit agent. Cost-aware model routing, fallback chains, Bayesian skill routing. Embedded llama.cpp, MCP server, programmatic SDK. MIT.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|