@kernel.chat/kbot 2.27.0 → 3.0.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 +15 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +187 -48
- package/dist/agent.js.map +1 -1
- package/dist/checkpoint.d.ts +79 -0
- package/dist/checkpoint.d.ts.map +1 -0
- package/dist/checkpoint.js +220 -0
- package/dist/checkpoint.js.map +1 -0
- package/dist/cli.js +55 -4
- package/dist/cli.js.map +1 -1
- package/dist/ide/bridge.d.ts +2 -0
- package/dist/ide/bridge.d.ts.map +1 -1
- package/dist/ide/bridge.js +1 -0
- package/dist/ide/bridge.js.map +1 -1
- package/dist/ide/mcp-server.d.ts.map +1 -1
- package/dist/ide/mcp-server.js +27 -7
- package/dist/ide/mcp-server.js.map +1 -1
- package/dist/learned-router.d.ts +9 -7
- package/dist/learned-router.d.ts.map +1 -1
- package/dist/learned-router.js +36 -10
- package/dist/learned-router.js.map +1 -1
- package/dist/learning.d.ts +4 -0
- package/dist/learning.d.ts.map +1 -1
- package/dist/learning.js +17 -0
- package/dist/learning.js.map +1 -1
- package/dist/multimodal.d.ts +6 -0
- package/dist/multimodal.d.ts.map +1 -1
- package/dist/multimodal.js +45 -0
- package/dist/multimodal.js.map +1 -1
- package/dist/sdk.d.ts +165 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/sdk.js +230 -0
- package/dist/sdk.js.map +1 -0
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +38 -0
- package/dist/serve.js.map +1 -1
- package/dist/skill-rating.d.ts +92 -0
- package/dist/skill-rating.d.ts.map +1 -0
- package/dist/skill-rating.js +352 -0
- package/dist/skill-rating.js.map +1 -0
- package/dist/streaming.d.ts +75 -1
- package/dist/streaming.d.ts.map +1 -1
- package/dist/streaming.js +211 -3
- package/dist/streaming.js.map +1 -1
- package/dist/task-ledger.d.ts +10 -0
- package/dist/task-ledger.d.ts.map +1 -1
- package/dist/task-ledger.js +28 -0
- package/dist/task-ledger.js.map +1 -1
- package/dist/telemetry.d.ts +52 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +219 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/terminal-caps.d.ts +20 -0
- package/dist/terminal-caps.d.ts.map +1 -0
- package/dist/terminal-caps.js +80 -0
- package/dist/terminal-caps.js.map +1 -0
- package/dist/tool-pipeline.d.ts +86 -0
- package/dist/tool-pipeline.d.ts.map +1 -0
- package/dist/tool-pipeline.js +200 -0
- package/dist/tool-pipeline.js.map +1 -0
- package/dist/tools/index.d.ts +45 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +168 -108
- package/dist/tools/index.js.map +1 -1
- package/dist/tui.d.ts +1 -0
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +71 -11
- package/dist/tui.js.map +1 -1
- package/dist/ui-adapter.d.ts +73 -0
- package/dist/ui-adapter.d.ts.map +1 -0
- package/dist/ui-adapter.js +139 -0
- package/dist/ui-adapter.js.map +1 -0
- package/dist/ui.d.ts +3 -0
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +21 -2
- package/dist/ui.js.map +1 -1
- package/package.json +22 -3
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
// K:BOT Telemetry — Structured JSON event logging, local-only
|
|
2
|
+
//
|
|
3
|
+
// Writes telemetry events to ~/.kbot/telemetry/ as NDJSON files (one per day).
|
|
4
|
+
// No external reporting — all data stays on the user's machine.
|
|
5
|
+
// Events are buffered in memory and flushed every 5 seconds or 50 events,
|
|
6
|
+
// whichever comes first.
|
|
7
|
+
//
|
|
8
|
+
// NDJSON format: one JSON object per line, newline-separated.
|
|
9
|
+
// File naming: YYYY-MM-DD.ndjson
|
|
10
|
+
//
|
|
11
|
+
// Event types:
|
|
12
|
+
// session_start / session_end — session lifecycle
|
|
13
|
+
// tool_call_start / tool_call_end / tool_call_error — tool execution
|
|
14
|
+
// checkpoint_save / checkpoint_resume — checkpoint system
|
|
15
|
+
// agent_route — agent routing decisions
|
|
16
|
+
// api_call / api_error — LLM API interactions
|
|
17
|
+
// cost_update — cumulative cost tracking
|
|
18
|
+
import { homedir } from 'node:os';
|
|
19
|
+
import { join } from 'node:path';
|
|
20
|
+
import { mkdir, appendFile, readFile, readdir, unlink, stat } from 'node:fs/promises';
|
|
21
|
+
import { existsSync } from 'node:fs';
|
|
22
|
+
// ── Constants ──
|
|
23
|
+
const TELEMETRY_DIR = join(homedir(), '.kbot', 'telemetry');
|
|
24
|
+
const FLUSH_INTERVAL_MS = 5_000; // Flush every 5 seconds
|
|
25
|
+
const FLUSH_THRESHOLD = 50; // Or when buffer reaches 50 events
|
|
26
|
+
const DEFAULT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
|
|
27
|
+
// ── TelemetryEmitter ──
|
|
28
|
+
export class TelemetryEmitter {
|
|
29
|
+
dir;
|
|
30
|
+
sessionId;
|
|
31
|
+
buffer = [];
|
|
32
|
+
flushTimer = null;
|
|
33
|
+
initialized = false;
|
|
34
|
+
flushing = false;
|
|
35
|
+
constructor(sessionId, dir) {
|
|
36
|
+
this.sessionId = sessionId;
|
|
37
|
+
this.dir = dir || TELEMETRY_DIR;
|
|
38
|
+
// Start periodic flush
|
|
39
|
+
this.flushTimer = setInterval(() => {
|
|
40
|
+
this.flush().catch(() => {
|
|
41
|
+
// Flush errors are non-critical — events may be lost but agent keeps running
|
|
42
|
+
});
|
|
43
|
+
}, FLUSH_INTERVAL_MS);
|
|
44
|
+
// Prevent the timer from keeping the process alive
|
|
45
|
+
if (this.flushTimer && typeof this.flushTimer.unref === 'function') {
|
|
46
|
+
this.flushTimer.unref();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** Ensure the telemetry directory exists */
|
|
50
|
+
async ensureDir() {
|
|
51
|
+
if (this.initialized)
|
|
52
|
+
return;
|
|
53
|
+
if (!existsSync(this.dir)) {
|
|
54
|
+
await mkdir(this.dir, { recursive: true });
|
|
55
|
+
}
|
|
56
|
+
this.initialized = true;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Emit a telemetry event. Buffers it in memory.
|
|
60
|
+
* When the buffer reaches FLUSH_THRESHOLD, triggers an immediate flush.
|
|
61
|
+
*/
|
|
62
|
+
emit(event, data, duration_ms) {
|
|
63
|
+
const telemetryEvent = {
|
|
64
|
+
timestamp: Date.now(),
|
|
65
|
+
sessionId: this.sessionId,
|
|
66
|
+
event,
|
|
67
|
+
data,
|
|
68
|
+
};
|
|
69
|
+
if (duration_ms !== undefined) {
|
|
70
|
+
telemetryEvent.duration_ms = duration_ms;
|
|
71
|
+
}
|
|
72
|
+
this.buffer.push(telemetryEvent);
|
|
73
|
+
// Flush immediately if buffer is full
|
|
74
|
+
if (this.buffer.length >= FLUSH_THRESHOLD) {
|
|
75
|
+
this.flush().catch(() => {
|
|
76
|
+
// Non-critical
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Flush buffered events to the daily NDJSON file.
|
|
82
|
+
* Each event is one JSON line, appended atomically.
|
|
83
|
+
*/
|
|
84
|
+
async flush() {
|
|
85
|
+
if (this.buffer.length === 0)
|
|
86
|
+
return;
|
|
87
|
+
if (this.flushing)
|
|
88
|
+
return; // Prevent concurrent flushes
|
|
89
|
+
this.flushing = true;
|
|
90
|
+
try {
|
|
91
|
+
await this.ensureDir();
|
|
92
|
+
// Drain buffer atomically
|
|
93
|
+
const events = this.buffer.splice(0);
|
|
94
|
+
// Group events by date (in case buffer spans midnight)
|
|
95
|
+
const byDate = new Map();
|
|
96
|
+
for (const event of events) {
|
|
97
|
+
const dateKey = new Date(event.timestamp).toISOString().slice(0, 10); // YYYY-MM-DD
|
|
98
|
+
const existing = byDate.get(dateKey) || [];
|
|
99
|
+
existing.push(event);
|
|
100
|
+
byDate.set(dateKey, existing);
|
|
101
|
+
}
|
|
102
|
+
// Append to each day's file
|
|
103
|
+
for (const [dateKey, dayEvents] of byDate) {
|
|
104
|
+
const filePath = join(this.dir, `${dateKey}.ndjson`);
|
|
105
|
+
const lines = dayEvents.map(e => JSON.stringify(e)).join('\n') + '\n';
|
|
106
|
+
await appendFile(filePath, lines, 'utf-8');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Telemetry writes failing should never crash the agent
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
this.flushing = false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Read all telemetry events for a specific session.
|
|
118
|
+
* Scans all NDJSON files and filters by sessionId.
|
|
119
|
+
*/
|
|
120
|
+
async getSessionEvents(sessionId) {
|
|
121
|
+
await this.ensureDir();
|
|
122
|
+
let files;
|
|
123
|
+
try {
|
|
124
|
+
files = await readdir(this.dir);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
const ndjsonFiles = files
|
|
130
|
+
.filter(f => f.endsWith('.ndjson'))
|
|
131
|
+
.sort(); // chronological order
|
|
132
|
+
const events = [];
|
|
133
|
+
for (const file of ndjsonFiles) {
|
|
134
|
+
try {
|
|
135
|
+
const content = await readFile(join(this.dir, file), 'utf-8');
|
|
136
|
+
const lines = content.split('\n').filter(line => line.trim());
|
|
137
|
+
for (const line of lines) {
|
|
138
|
+
try {
|
|
139
|
+
const event = JSON.parse(line);
|
|
140
|
+
if (event.sessionId === sessionId) {
|
|
141
|
+
events.push(event);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// Skip malformed lines
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// Skip unreadable files
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return events;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Remove telemetry files older than maxAge.
|
|
157
|
+
* Returns the number of files removed.
|
|
158
|
+
*/
|
|
159
|
+
async cleanup(maxAge) {
|
|
160
|
+
await this.ensureDir();
|
|
161
|
+
const maxAgeMs = maxAge ?? DEFAULT_MAX_AGE_MS;
|
|
162
|
+
const cutoff = Date.now() - maxAgeMs;
|
|
163
|
+
let removed = 0;
|
|
164
|
+
let files;
|
|
165
|
+
try {
|
|
166
|
+
files = await readdir(this.dir);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
for (const file of files) {
|
|
172
|
+
if (!file.endsWith('.ndjson'))
|
|
173
|
+
continue;
|
|
174
|
+
const filePath = join(this.dir, file);
|
|
175
|
+
try {
|
|
176
|
+
const fileStat = await stat(filePath);
|
|
177
|
+
if (fileStat.mtimeMs < cutoff) {
|
|
178
|
+
await unlink(filePath);
|
|
179
|
+
removed++;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
// File may have been removed — ignore
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return removed;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Flush remaining events and stop the periodic flush timer.
|
|
190
|
+
* Call this when the session ends or the process is exiting.
|
|
191
|
+
*/
|
|
192
|
+
async destroy() {
|
|
193
|
+
if (this.flushTimer) {
|
|
194
|
+
clearInterval(this.flushTimer);
|
|
195
|
+
this.flushTimer = null;
|
|
196
|
+
}
|
|
197
|
+
// Final flush
|
|
198
|
+
await this.flush();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// ── Convenience: module-level singleton ──
|
|
202
|
+
let _instance = null;
|
|
203
|
+
export function getTelemetryEmitter(sessionId) {
|
|
204
|
+
if (!_instance) {
|
|
205
|
+
if (!sessionId)
|
|
206
|
+
throw new Error('TelemetryEmitter requires a sessionId on first call');
|
|
207
|
+
_instance = new TelemetryEmitter(sessionId);
|
|
208
|
+
}
|
|
209
|
+
return _instance;
|
|
210
|
+
}
|
|
211
|
+
export function destroyTelemetryEmitter() {
|
|
212
|
+
if (_instance) {
|
|
213
|
+
const p = _instance.destroy();
|
|
214
|
+
_instance = null;
|
|
215
|
+
return p;
|
|
216
|
+
}
|
|
217
|
+
return Promise.resolve();
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface TerminalCapabilities {
|
|
2
|
+
truecolor: boolean;
|
|
3
|
+
color256: boolean;
|
|
4
|
+
basicColor: boolean;
|
|
5
|
+
sixel: boolean;
|
|
6
|
+
kittyGraphics: boolean;
|
|
7
|
+
iterm2Images: boolean;
|
|
8
|
+
unicode: boolean;
|
|
9
|
+
braille: boolean;
|
|
10
|
+
syncOutput: boolean;
|
|
11
|
+
program: string;
|
|
12
|
+
columns: number;
|
|
13
|
+
rows: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function detectTerminalCapabilities(): TerminalCapabilities;
|
|
16
|
+
export declare function withSyncOutput(fn: () => void): void;
|
|
17
|
+
export declare function rgb(r: number, g: number, b: number): string;
|
|
18
|
+
export declare function bgRgb(r: number, g: number, b: number): string;
|
|
19
|
+
export declare function gradient(text: string, startColor: [number, number, number], endColor: [number, number, number]): string;
|
|
20
|
+
//# sourceMappingURL=terminal-caps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-caps.d.ts","sourceRoot":"","sources":["../src/terminal-caps.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,oBAAoB;IAEnC,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IAGpB,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IAGtB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IAGjB,UAAU,EAAE,OAAO,CAAC;IAGpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,0BAA0B,IAAI,oBAAoB,CAyCjE;AAKD,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAYnD;AAKD,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CASvH"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// K:BOT Terminal Capability Detection — zero dependencies
|
|
2
|
+
//
|
|
3
|
+
// Detects what the current terminal supports and provides feature flags.
|
|
4
|
+
// Enables progressive enhancement: Braille sparklines, inline images
|
|
5
|
+
// (Sixel/Kitty/iTerm2), synchronized output, and truecolor gradients.
|
|
6
|
+
//
|
|
7
|
+
// Everything degrades gracefully — if detection fails, callers fall back
|
|
8
|
+
// to existing basic output.
|
|
9
|
+
export function detectTerminalCapabilities() {
|
|
10
|
+
const env = process.env;
|
|
11
|
+
const program = env.TERM_PROGRAM ?? env.TERMINAL_EMULATOR ?? '';
|
|
12
|
+
const colorterm = env.COLORTERM ?? '';
|
|
13
|
+
const term = env.TERM ?? '';
|
|
14
|
+
// Color detection
|
|
15
|
+
const truecolor = colorterm === 'truecolor' || colorterm === '24bit'
|
|
16
|
+
|| ['iterm2', 'wezterm', 'kitty', 'alacritty', 'rio'].some(t => program.toLowerCase().includes(t));
|
|
17
|
+
const color256 = truecolor || term.includes('256color');
|
|
18
|
+
const basicColor = color256 || process.stdout.isTTY === true;
|
|
19
|
+
// Graphics detection
|
|
20
|
+
const kittyGraphics = program.toLowerCase() === 'kitty' || env.KITTY_WINDOW_ID !== undefined;
|
|
21
|
+
const iterm2Images = program === 'iTerm.app' || program === 'WezTerm' || env.ITERM_SESSION_ID !== undefined;
|
|
22
|
+
const sixel = ['mlterm', 'xterm', 'foot', 'contour'].some(t => program.toLowerCase().includes(t))
|
|
23
|
+
|| term === 'xterm-sixel';
|
|
24
|
+
// Unicode/Braille
|
|
25
|
+
const locale = env.LANG ?? env.LC_ALL ?? '';
|
|
26
|
+
const unicode = locale.includes('UTF-8') || locale.includes('utf-8') || locale.includes('UTF8');
|
|
27
|
+
const braille = unicode; // Braille requires Unicode
|
|
28
|
+
// Synchronized output (most modern terminals support it)
|
|
29
|
+
const syncOutput = kittyGraphics || iterm2Images
|
|
30
|
+
|| ['wezterm', 'contour', 'foot', 'rio'].some(t => program.toLowerCase().includes(t));
|
|
31
|
+
return {
|
|
32
|
+
truecolor,
|
|
33
|
+
color256,
|
|
34
|
+
basicColor,
|
|
35
|
+
sixel,
|
|
36
|
+
kittyGraphics,
|
|
37
|
+
iterm2Images,
|
|
38
|
+
unicode,
|
|
39
|
+
braille,
|
|
40
|
+
syncOutput,
|
|
41
|
+
program: program || term || 'unknown',
|
|
42
|
+
columns: process.stdout.columns ?? 80,
|
|
43
|
+
rows: process.stdout.rows ?? 24,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// ── Synchronized output wrapper ──
|
|
47
|
+
// Prevents flicker by buffering screen updates between begin/end markers.
|
|
48
|
+
export function withSyncOutput(fn) {
|
|
49
|
+
const caps = detectTerminalCapabilities();
|
|
50
|
+
if (caps.syncOutput) {
|
|
51
|
+
process.stdout.write('\x1b[?2026h'); // Begin synchronized update
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
fn();
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
if (caps.syncOutput) {
|
|
58
|
+
process.stdout.write('\x1b[?2026l'); // End synchronized update
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// ── Truecolor helpers ──
|
|
63
|
+
// Generate ANSI escape sequences for 24-bit color terminals.
|
|
64
|
+
export function rgb(r, g, b) {
|
|
65
|
+
return `\x1b[38;2;${r};${g};${b}m`;
|
|
66
|
+
}
|
|
67
|
+
export function bgRgb(r, g, b) {
|
|
68
|
+
return `\x1b[48;2;${r};${g};${b}m`;
|
|
69
|
+
}
|
|
70
|
+
export function gradient(text, startColor, endColor) {
|
|
71
|
+
const chars = [...text];
|
|
72
|
+
return chars.map((char, i) => {
|
|
73
|
+
const t = chars.length > 1 ? i / (chars.length - 1) : 0;
|
|
74
|
+
const r = Math.round(startColor[0] + (endColor[0] - startColor[0]) * t);
|
|
75
|
+
const g = Math.round(startColor[1] + (endColor[1] - startColor[1]) * t);
|
|
76
|
+
const b = Math.round(startColor[2] + (endColor[2] - startColor[2]) * t);
|
|
77
|
+
return `${rgb(r, g, b)}${char}`;
|
|
78
|
+
}).join('') + '\x1b[0m';
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=terminal-caps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-caps.js","sourceRoot":"","sources":["../src/terminal-caps.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export interface ToolContext {
|
|
2
|
+
toolName: string;
|
|
3
|
+
toolArgs: Record<string, any>;
|
|
4
|
+
toolCallId: string;
|
|
5
|
+
result?: string;
|
|
6
|
+
error?: string;
|
|
7
|
+
durationMs?: number;
|
|
8
|
+
metadata: Record<string, any>;
|
|
9
|
+
aborted: boolean;
|
|
10
|
+
abortReason?: string;
|
|
11
|
+
}
|
|
12
|
+
export type NextFunction = () => Promise<void>;
|
|
13
|
+
export type ToolMiddleware = (ctx: ToolContext, next: NextFunction) => Promise<void>;
|
|
14
|
+
export declare class ToolPipeline {
|
|
15
|
+
private middleware;
|
|
16
|
+
/** Append middleware to the end of the pipeline */
|
|
17
|
+
use(mw: ToolMiddleware): this;
|
|
18
|
+
/** Insert middleware at a specific position */
|
|
19
|
+
useAt(index: number, mw: ToolMiddleware): this;
|
|
20
|
+
/** Remove middleware by reference */
|
|
21
|
+
remove(mw: ToolMiddleware): this;
|
|
22
|
+
/** Execute the pipeline for a tool context */
|
|
23
|
+
execute(ctx: ToolContext): Promise<ToolContext>;
|
|
24
|
+
/** Number of middleware in the pipeline */
|
|
25
|
+
get length(): number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Permission check middleware.
|
|
29
|
+
* Blocks tool execution if the user denies the operation.
|
|
30
|
+
*/
|
|
31
|
+
export declare function permissionMiddleware(checkPermission: (name: string, args: any) => Promise<boolean>): ToolMiddleware;
|
|
32
|
+
/**
|
|
33
|
+
* Pre/post hook middleware.
|
|
34
|
+
* Runs user-defined hooks before and after tool execution.
|
|
35
|
+
*/
|
|
36
|
+
export declare function hookMiddleware(runPreHook: (name: string, args: any) => {
|
|
37
|
+
blocked: boolean;
|
|
38
|
+
blockReason?: string;
|
|
39
|
+
}, runPostHook: (name: string, args: any, result: string) => void): ToolMiddleware;
|
|
40
|
+
/**
|
|
41
|
+
* Timeout middleware.
|
|
42
|
+
* Aborts tool execution if it exceeds the configured timeout.
|
|
43
|
+
*/
|
|
44
|
+
export declare function timeoutMiddleware(defaultTimeout?: number): ToolMiddleware;
|
|
45
|
+
/**
|
|
46
|
+
* Metrics recording middleware.
|
|
47
|
+
* Records execution duration and error state.
|
|
48
|
+
*/
|
|
49
|
+
export declare function metricsMiddleware(recordMetrics: (name: string, duration: number, error?: string) => void): ToolMiddleware;
|
|
50
|
+
/**
|
|
51
|
+
* Result truncation middleware.
|
|
52
|
+
* Truncates tool output that exceeds maxSize characters.
|
|
53
|
+
*/
|
|
54
|
+
export declare function truncationMiddleware(maxSize?: number): ToolMiddleware;
|
|
55
|
+
/**
|
|
56
|
+
* Telemetry middleware.
|
|
57
|
+
* Emits tool_call_start and tool_call_end events.
|
|
58
|
+
*/
|
|
59
|
+
export declare function telemetryMiddleware(emit: (event: string, data: any) => void): ToolMiddleware;
|
|
60
|
+
/**
|
|
61
|
+
* Execution middleware — the actual tool call.
|
|
62
|
+
* This should be the last middleware in the pipeline.
|
|
63
|
+
*/
|
|
64
|
+
export declare function executionMiddleware(executeTool: (name: string, args: any) => Promise<{
|
|
65
|
+
result: string;
|
|
66
|
+
error?: string;
|
|
67
|
+
}>): ToolMiddleware;
|
|
68
|
+
/**
|
|
69
|
+
* Create the default pipeline with the standard middleware stack.
|
|
70
|
+
* Order: telemetry? → permission → hooks → metrics → timeout → truncation → execution
|
|
71
|
+
*/
|
|
72
|
+
export declare function createDefaultPipeline(deps: {
|
|
73
|
+
checkPermission: (name: string, args: any) => Promise<boolean>;
|
|
74
|
+
runPreHook: (name: string, args: any) => {
|
|
75
|
+
blocked: boolean;
|
|
76
|
+
blockReason?: string;
|
|
77
|
+
};
|
|
78
|
+
runPostHook: (name: string, args: any, result: string) => void;
|
|
79
|
+
executeTool: (name: string, args: any) => Promise<{
|
|
80
|
+
result: string;
|
|
81
|
+
error?: string;
|
|
82
|
+
}>;
|
|
83
|
+
recordMetrics: (name: string, duration: number, error?: string) => void;
|
|
84
|
+
emit?: (event: string, data: any) => void;
|
|
85
|
+
}): ToolPipeline;
|
|
86
|
+
//# sourceMappingURL=tool-pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-pipeline.d.ts","sourceRoot":"","sources":["../src/tool-pipeline.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC7B,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC7B,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;AAC9C,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEpF,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAuB;IAEzC,mDAAmD;IACnD,GAAG,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI;IAK7B,+CAA+C;IAC/C,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,cAAc,GAAG,IAAI;IAK9C,qCAAqC;IACrC,MAAM,CAAC,EAAE,EAAE,cAAc,GAAG,IAAI;IAMhC,8CAA8C;IACxC,OAAO,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAYrD,2CAA2C;IAC3C,IAAI,MAAM,IAAI,MAAM,CAEnB;CACF;AAKD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,OAAO,CAAC,GAC7D,cAAc,CAWhB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EACnF,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GAC7D,cAAc,CAchB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,GAAE,MAAgB,GAAG,cAAc,CA2BlF;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,GACtE,cAAc,CAOhB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,MAAe,GAAG,cAAc,CAS7E;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,GACvC,cAAc,CAWhB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GACpF,cAAc,CAWhB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC9D,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACnF,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9D,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACrF,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IACvE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAA;CAC1C,GAAG,YAAY,CAcf"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// K:BOT Tool Execution Middleware Pipeline
|
|
2
|
+
// Composable Express/Koa-style middleware stack for tool execution.
|
|
3
|
+
// Each middleware calls next() to continue the chain.
|
|
4
|
+
//
|
|
5
|
+
// Order matters: first added = outermost (runs first on the way in, last on the way out).
|
|
6
|
+
// The execution middleware should always be last.
|
|
7
|
+
//
|
|
8
|
+
// Usage:
|
|
9
|
+
// const pipeline = new ToolPipeline()
|
|
10
|
+
// pipeline.use(permissionMiddleware(checkPermission))
|
|
11
|
+
// pipeline.use(metricsMiddleware(recordMetrics))
|
|
12
|
+
// pipeline.use(executionMiddleware(executeTool))
|
|
13
|
+
// await pipeline.execute(ctx)
|
|
14
|
+
export class ToolPipeline {
|
|
15
|
+
middleware = [];
|
|
16
|
+
/** Append middleware to the end of the pipeline */
|
|
17
|
+
use(mw) {
|
|
18
|
+
this.middleware.push(mw);
|
|
19
|
+
return this;
|
|
20
|
+
}
|
|
21
|
+
/** Insert middleware at a specific position */
|
|
22
|
+
useAt(index, mw) {
|
|
23
|
+
this.middleware.splice(index, 0, mw);
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
/** Remove middleware by reference */
|
|
27
|
+
remove(mw) {
|
|
28
|
+
const idx = this.middleware.indexOf(mw);
|
|
29
|
+
if (idx !== -1)
|
|
30
|
+
this.middleware.splice(idx, 1);
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
/** Execute the pipeline for a tool context */
|
|
34
|
+
async execute(ctx) {
|
|
35
|
+
let index = 0;
|
|
36
|
+
const next = async () => {
|
|
37
|
+
if (ctx.aborted)
|
|
38
|
+
return;
|
|
39
|
+
if (index >= this.middleware.length)
|
|
40
|
+
return;
|
|
41
|
+
const mw = this.middleware[index++];
|
|
42
|
+
await mw(ctx, next);
|
|
43
|
+
};
|
|
44
|
+
await next();
|
|
45
|
+
return ctx;
|
|
46
|
+
}
|
|
47
|
+
/** Number of middleware in the pipeline */
|
|
48
|
+
get length() {
|
|
49
|
+
return this.middleware.length;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// ── Built-in middleware factories ──
|
|
53
|
+
/**
|
|
54
|
+
* Permission check middleware.
|
|
55
|
+
* Blocks tool execution if the user denies the operation.
|
|
56
|
+
*/
|
|
57
|
+
export function permissionMiddleware(checkPermission) {
|
|
58
|
+
return async (ctx, next) => {
|
|
59
|
+
const allowed = await checkPermission(ctx.toolName, ctx.toolArgs);
|
|
60
|
+
if (!allowed) {
|
|
61
|
+
ctx.aborted = true;
|
|
62
|
+
ctx.abortReason = 'Permission denied by user';
|
|
63
|
+
ctx.error = 'Tool call was denied by user';
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
await next();
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Pre/post hook middleware.
|
|
71
|
+
* Runs user-defined hooks before and after tool execution.
|
|
72
|
+
*/
|
|
73
|
+
export function hookMiddleware(runPreHook, runPostHook) {
|
|
74
|
+
return async (ctx, next) => {
|
|
75
|
+
const preResult = runPreHook(ctx.toolName, ctx.toolArgs);
|
|
76
|
+
if (preResult.blocked) {
|
|
77
|
+
ctx.aborted = true;
|
|
78
|
+
ctx.abortReason = preResult.blockReason ?? 'Blocked by pre-tool hook';
|
|
79
|
+
ctx.error = `Blocked by hook: ${ctx.abortReason}`;
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
await next();
|
|
83
|
+
if (ctx.result && !ctx.error) {
|
|
84
|
+
runPostHook(ctx.toolName, ctx.toolArgs, ctx.result);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Timeout middleware.
|
|
90
|
+
* Aborts tool execution if it exceeds the configured timeout.
|
|
91
|
+
*/
|
|
92
|
+
export function timeoutMiddleware(defaultTimeout = 300_000) {
|
|
93
|
+
return async (ctx, next) => {
|
|
94
|
+
const timeout = ctx.metadata.timeout ?? defaultTimeout;
|
|
95
|
+
const controller = new AbortController();
|
|
96
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
97
|
+
ctx.metadata.abortController = controller;
|
|
98
|
+
try {
|
|
99
|
+
await Promise.race([
|
|
100
|
+
next(),
|
|
101
|
+
new Promise((_, reject) => {
|
|
102
|
+
controller.signal.addEventListener('abort', () => {
|
|
103
|
+
reject(new Error(`Tool ${ctx.toolName} timed out after ${timeout}ms`));
|
|
104
|
+
});
|
|
105
|
+
}),
|
|
106
|
+
]);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
if (err.message?.includes('timed out')) {
|
|
110
|
+
ctx.error = err.message;
|
|
111
|
+
ctx.aborted = true;
|
|
112
|
+
ctx.abortReason = 'Execution timed out';
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
throw err;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
clearTimeout(timer);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Metrics recording middleware.
|
|
125
|
+
* Records execution duration and error state.
|
|
126
|
+
*/
|
|
127
|
+
export function metricsMiddleware(recordMetrics) {
|
|
128
|
+
return async (ctx, next) => {
|
|
129
|
+
const start = Date.now();
|
|
130
|
+
await next();
|
|
131
|
+
ctx.durationMs = Date.now() - start;
|
|
132
|
+
recordMetrics(ctx.toolName, ctx.durationMs, ctx.error);
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Result truncation middleware.
|
|
137
|
+
* Truncates tool output that exceeds maxSize characters.
|
|
138
|
+
*/
|
|
139
|
+
export function truncationMiddleware(maxSize = 50_000) {
|
|
140
|
+
return async (ctx, next) => {
|
|
141
|
+
await next();
|
|
142
|
+
if (ctx.result && ctx.result.length > maxSize) {
|
|
143
|
+
const remaining = ctx.result.length - maxSize;
|
|
144
|
+
ctx.result = ctx.result.slice(0, maxSize) +
|
|
145
|
+
`\n\n[... truncated ${remaining} characters. Use more specific queries to get focused results.]`;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Telemetry middleware.
|
|
151
|
+
* Emits tool_call_start and tool_call_end events.
|
|
152
|
+
*/
|
|
153
|
+
export function telemetryMiddleware(emit) {
|
|
154
|
+
return async (ctx, next) => {
|
|
155
|
+
emit('tool_call_start', { tool: ctx.toolName, args: ctx.toolArgs });
|
|
156
|
+
await next();
|
|
157
|
+
emit('tool_call_end', {
|
|
158
|
+
tool: ctx.toolName,
|
|
159
|
+
duration_ms: ctx.durationMs,
|
|
160
|
+
success: !ctx.error,
|
|
161
|
+
error: ctx.error,
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Execution middleware — the actual tool call.
|
|
167
|
+
* This should be the last middleware in the pipeline.
|
|
168
|
+
*/
|
|
169
|
+
export function executionMiddleware(executeTool) {
|
|
170
|
+
return async (ctx, next) => {
|
|
171
|
+
try {
|
|
172
|
+
const result = await executeTool(ctx.toolName, ctx.toolArgs);
|
|
173
|
+
ctx.result = result.result;
|
|
174
|
+
if (result.error)
|
|
175
|
+
ctx.error = result.error;
|
|
176
|
+
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
ctx.error = err.message ?? String(err);
|
|
179
|
+
}
|
|
180
|
+
await next(); // allow post-execution middleware
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Create the default pipeline with the standard middleware stack.
|
|
185
|
+
* Order: telemetry? → permission → hooks → metrics → timeout → truncation → execution
|
|
186
|
+
*/
|
|
187
|
+
export function createDefaultPipeline(deps) {
|
|
188
|
+
const pipeline = new ToolPipeline();
|
|
189
|
+
if (deps.emit) {
|
|
190
|
+
pipeline.use(telemetryMiddleware(deps.emit));
|
|
191
|
+
}
|
|
192
|
+
pipeline.use(permissionMiddleware(deps.checkPermission));
|
|
193
|
+
pipeline.use(hookMiddleware(deps.runPreHook, deps.runPostHook));
|
|
194
|
+
pipeline.use(metricsMiddleware(deps.recordMetrics));
|
|
195
|
+
pipeline.use(timeoutMiddleware());
|
|
196
|
+
pipeline.use(truncationMiddleware());
|
|
197
|
+
pipeline.use(executionMiddleware(deps.executeTool));
|
|
198
|
+
return pipeline;
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=tool-pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-pipeline.js","sourceRoot":"","sources":["../src/tool-pipeline.ts"],"names":[],"mappings":"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"}
|