@kernel.chat/kbot 2.26.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.
Files changed (97) hide show
  1. package/dist/agent.d.ts +15 -0
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +187 -48
  4. package/dist/agent.js.map +1 -1
  5. package/dist/checkpoint.d.ts +79 -0
  6. package/dist/checkpoint.d.ts.map +1 -0
  7. package/dist/checkpoint.js +220 -0
  8. package/dist/checkpoint.js.map +1 -0
  9. package/dist/cli.js +55 -4
  10. package/dist/cli.js.map +1 -1
  11. package/dist/ide/bridge.d.ts +2 -0
  12. package/dist/ide/bridge.d.ts.map +1 -1
  13. package/dist/ide/bridge.js +1 -0
  14. package/dist/ide/bridge.js.map +1 -1
  15. package/dist/ide/mcp-server.d.ts.map +1 -1
  16. package/dist/ide/mcp-server.js +27 -7
  17. package/dist/ide/mcp-server.js.map +1 -1
  18. package/dist/learned-router.d.ts +9 -7
  19. package/dist/learned-router.d.ts.map +1 -1
  20. package/dist/learned-router.js +36 -10
  21. package/dist/learned-router.js.map +1 -1
  22. package/dist/learning.d.ts +4 -0
  23. package/dist/learning.d.ts.map +1 -1
  24. package/dist/learning.js +17 -0
  25. package/dist/learning.js.map +1 -1
  26. package/dist/mcp-plugins.js +1 -1
  27. package/dist/mcp-plugins.js.map +1 -1
  28. package/dist/multimodal.d.ts +6 -0
  29. package/dist/multimodal.d.ts.map +1 -1
  30. package/dist/multimodal.js +45 -0
  31. package/dist/multimodal.js.map +1 -1
  32. package/dist/sdk.d.ts +165 -0
  33. package/dist/sdk.d.ts.map +1 -0
  34. package/dist/sdk.js +230 -0
  35. package/dist/sdk.js.map +1 -0
  36. package/dist/serve.d.ts.map +1 -1
  37. package/dist/serve.js +38 -0
  38. package/dist/serve.js.map +1 -1
  39. package/dist/skill-rating.d.ts +92 -0
  40. package/dist/skill-rating.d.ts.map +1 -0
  41. package/dist/skill-rating.js +352 -0
  42. package/dist/skill-rating.js.map +1 -0
  43. package/dist/streaming.d.ts +75 -1
  44. package/dist/streaming.d.ts.map +1 -1
  45. package/dist/streaming.js +211 -3
  46. package/dist/streaming.js.map +1 -1
  47. package/dist/task-ledger.d.ts +10 -0
  48. package/dist/task-ledger.d.ts.map +1 -1
  49. package/dist/task-ledger.js +28 -0
  50. package/dist/task-ledger.js.map +1 -1
  51. package/dist/telemetry.d.ts +52 -0
  52. package/dist/telemetry.d.ts.map +1 -0
  53. package/dist/telemetry.js +219 -0
  54. package/dist/telemetry.js.map +1 -0
  55. package/dist/terminal-caps.d.ts +20 -0
  56. package/dist/terminal-caps.d.ts.map +1 -0
  57. package/dist/terminal-caps.js +80 -0
  58. package/dist/terminal-caps.js.map +1 -0
  59. package/dist/tool-pipeline.d.ts +86 -0
  60. package/dist/tool-pipeline.d.ts.map +1 -0
  61. package/dist/tool-pipeline.js +200 -0
  62. package/dist/tool-pipeline.js.map +1 -0
  63. package/dist/tools/containers.js +7 -7
  64. package/dist/tools/containers.js.map +1 -1
  65. package/dist/tools/database.js +6 -6
  66. package/dist/tools/database.js.map +1 -1
  67. package/dist/tools/deploy.js +3 -3
  68. package/dist/tools/deploy.js.map +1 -1
  69. package/dist/tools/e2b-sandbox.js +5 -5
  70. package/dist/tools/e2b-sandbox.js.map +1 -1
  71. package/dist/tools/index.d.ts +45 -1
  72. package/dist/tools/index.d.ts.map +1 -1
  73. package/dist/tools/index.js +168 -108
  74. package/dist/tools/index.js.map +1 -1
  75. package/dist/tools/index.test.js +1 -1
  76. package/dist/tools/index.test.js.map +1 -1
  77. package/dist/tools/research.js +1 -1
  78. package/dist/tools/research.js.map +1 -1
  79. package/dist/tools/training.js +7 -7
  80. package/dist/tools/training.js.map +1 -1
  81. package/dist/tools/vfx.js +2 -2
  82. package/dist/tools/vfx.js.map +1 -1
  83. package/dist/tui.d.ts +1 -0
  84. package/dist/tui.d.ts.map +1 -1
  85. package/dist/tui.js +71 -11
  86. package/dist/tui.js.map +1 -1
  87. package/dist/ui-adapter.d.ts +73 -0
  88. package/dist/ui-adapter.d.ts.map +1 -0
  89. package/dist/ui-adapter.js +139 -0
  90. package/dist/ui-adapter.js.map +1 -0
  91. package/dist/ui.d.ts +3 -0
  92. package/dist/ui.d.ts.map +1 -1
  93. package/dist/ui.js +21 -2
  94. package/dist/ui.js.map +1 -1
  95. package/dist/workflows.js +3 -3
  96. package/dist/workflows.js.map +1 -1
  97. 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":"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"}
@@ -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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"}