@kernel.chat/kbot 3.23.0 → 3.26.1

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 (85) hide show
  1. package/README.md +33 -22
  2. package/dist/agent.d.ts.map +1 -1
  3. package/dist/agent.js +3 -1
  4. package/dist/agent.js.map +1 -1
  5. package/dist/agents/trader.d.ts +32 -0
  6. package/dist/agents/trader.d.ts.map +1 -0
  7. package/dist/agents/trader.js +190 -0
  8. package/dist/agents/trader.js.map +1 -0
  9. package/dist/cli.js +219 -15
  10. package/dist/cli.js.map +1 -1
  11. package/dist/context.d.ts +4 -1
  12. package/dist/context.d.ts.map +1 -1
  13. package/dist/context.js +28 -1
  14. package/dist/context.js.map +1 -1
  15. package/dist/doctor.d.ts.map +1 -1
  16. package/dist/doctor.js +71 -1
  17. package/dist/doctor.js.map +1 -1
  18. package/dist/inference.d.ts +9 -0
  19. package/dist/inference.d.ts.map +1 -1
  20. package/dist/inference.js +38 -5
  21. package/dist/inference.js.map +1 -1
  22. package/dist/introspection.d.ts +17 -0
  23. package/dist/introspection.d.ts.map +1 -0
  24. package/dist/introspection.js +490 -0
  25. package/dist/introspection.js.map +1 -0
  26. package/dist/learned-router.d.ts.map +1 -1
  27. package/dist/learned-router.js +3 -0
  28. package/dist/learned-router.js.map +1 -1
  29. package/dist/machine.d.ts +85 -0
  30. package/dist/machine.d.ts.map +1 -0
  31. package/dist/machine.js +538 -0
  32. package/dist/machine.js.map +1 -0
  33. package/dist/matrix.d.ts.map +1 -1
  34. package/dist/matrix.js +11 -0
  35. package/dist/matrix.js.map +1 -1
  36. package/dist/provider-fallback.d.ts +6 -0
  37. package/dist/provider-fallback.d.ts.map +1 -1
  38. package/dist/provider-fallback.js +29 -0
  39. package/dist/provider-fallback.js.map +1 -1
  40. package/dist/synthesis-engine.d.ts +175 -0
  41. package/dist/synthesis-engine.d.ts.map +1 -0
  42. package/dist/synthesis-engine.js +783 -0
  43. package/dist/synthesis-engine.js.map +1 -0
  44. package/dist/tool-pipeline.d.ts +7 -1
  45. package/dist/tool-pipeline.d.ts.map +1 -1
  46. package/dist/tool-pipeline.js +39 -1
  47. package/dist/tool-pipeline.js.map +1 -1
  48. package/dist/tools/finance.d.ts +2 -0
  49. package/dist/tools/finance.d.ts.map +1 -0
  50. package/dist/tools/finance.js +1116 -0
  51. package/dist/tools/finance.js.map +1 -0
  52. package/dist/tools/finance.test.d.ts +2 -0
  53. package/dist/tools/finance.test.d.ts.map +1 -0
  54. package/dist/tools/finance.test.js +245 -0
  55. package/dist/tools/finance.test.js.map +1 -0
  56. package/dist/tools/index.d.ts.map +1 -1
  57. package/dist/tools/index.js +5 -0
  58. package/dist/tools/index.js.map +1 -1
  59. package/dist/tools/machine-tools.d.ts +2 -0
  60. package/dist/tools/machine-tools.d.ts.map +1 -0
  61. package/dist/tools/machine-tools.js +690 -0
  62. package/dist/tools/machine-tools.js.map +1 -0
  63. package/dist/tools/sentiment.d.ts +2 -0
  64. package/dist/tools/sentiment.d.ts.map +1 -0
  65. package/dist/tools/sentiment.js +513 -0
  66. package/dist/tools/sentiment.js.map +1 -0
  67. package/dist/tools/stocks.d.ts +2 -0
  68. package/dist/tools/stocks.d.ts.map +1 -0
  69. package/dist/tools/stocks.js +345 -0
  70. package/dist/tools/stocks.js.map +1 -0
  71. package/dist/tools/stocks.test.d.ts +2 -0
  72. package/dist/tools/stocks.test.d.ts.map +1 -0
  73. package/dist/tools/stocks.test.js +82 -0
  74. package/dist/tools/stocks.test.js.map +1 -0
  75. package/dist/tools/wallet.d.ts +2 -0
  76. package/dist/tools/wallet.d.ts.map +1 -0
  77. package/dist/tools/wallet.js +698 -0
  78. package/dist/tools/wallet.js.map +1 -0
  79. package/dist/tools/wallet.test.d.ts +2 -0
  80. package/dist/tools/wallet.test.d.ts.map +1 -0
  81. package/dist/tools/wallet.test.js +205 -0
  82. package/dist/tools/wallet.test.js.map +1 -0
  83. package/dist/ui.js +1 -1
  84. package/dist/ui.js.map +1 -1
  85. package/package.json +94 -42
@@ -0,0 +1,85 @@
1
+ export interface CpuInfo {
2
+ model: string;
3
+ chip?: string;
4
+ cores: number;
5
+ performanceCores?: number;
6
+ efficiencyCores?: number;
7
+ arch: string;
8
+ }
9
+ export interface GpuInfo {
10
+ model: string;
11
+ cores?: number;
12
+ vram?: string;
13
+ metal?: string;
14
+ cuda?: boolean;
15
+ driver?: string;
16
+ }
17
+ export interface MemoryInfo {
18
+ total: string;
19
+ totalBytes: number;
20
+ free: string;
21
+ freeBytes: number;
22
+ used: string;
23
+ usedBytes: number;
24
+ pressure: 'low' | 'moderate' | 'high';
25
+ }
26
+ export interface DiskInfo {
27
+ total: string;
28
+ available: string;
29
+ used: string;
30
+ usedPercent: number;
31
+ filesystem: string;
32
+ }
33
+ export interface DisplayInfo {
34
+ name: string;
35
+ resolution: string;
36
+ type?: string;
37
+ main: boolean;
38
+ }
39
+ export interface BatteryInfo {
40
+ present: boolean;
41
+ percent?: number;
42
+ charging?: boolean;
43
+ timeRemaining?: string;
44
+ }
45
+ export interface NetworkInfo {
46
+ hostname: string;
47
+ wifi?: string;
48
+ localIp?: string;
49
+ }
50
+ export interface DevTool {
51
+ name: string;
52
+ version: string;
53
+ }
54
+ export interface MachineProfile {
55
+ model?: string;
56
+ modelId?: string;
57
+ cpu: CpuInfo;
58
+ gpu: GpuInfo[];
59
+ memory: MemoryInfo;
60
+ disk: DiskInfo;
61
+ os: string;
62
+ osVersion: string;
63
+ kernel: string;
64
+ platform: string;
65
+ uptime: string;
66
+ displays: DisplayInfo[];
67
+ battery: BatteryInfo;
68
+ network: NetworkInfo;
69
+ shell: string;
70
+ user: string;
71
+ home: string;
72
+ devTools: DevTool[];
73
+ canRunLocalModels: boolean;
74
+ gpuAcceleration: 'metal' | 'cuda' | 'vulkan' | 'cpu-only';
75
+ recommendedModelSize: string;
76
+ probedAt: string;
77
+ }
78
+ export declare function probeMachine(): Promise<MachineProfile>;
79
+ /** Get the cached profile (null if probeMachine hasn't been called) */
80
+ export declare function getMachineProfile(): MachineProfile | null;
81
+ /** Force a fresh probe (clears cache) */
82
+ export declare function reprobeMachine(): Promise<MachineProfile>;
83
+ export declare function formatMachineProfile(p: MachineProfile): string;
84
+ export declare function formatMachineForPrompt(p: MachineProfile): string;
85
+ //# sourceMappingURL=machine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"machine.d.ts","sourceRoot":"","sources":["../src/machine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,538 @@
1
+ // kbot Machine Awareness — Full system profiler
2
+ //
3
+ // Probes hardware, OS, GPU, display, battery, network, dev tools.
4
+ // Cross-platform: macOS (system_profiler), Linux (/proc, lscpu, lspci).
5
+ // Cached after first probe — call probeMachine() once at startup.
6
+ //
7
+ // Usage:
8
+ // import { probeMachine, getMachineProfile } from './machine.js'
9
+ // await probeMachine() // probe once
10
+ // const profile = getMachineProfile() // read cached result
11
+ import { execSync } from 'node:child_process';
12
+ import { existsSync, readFileSync } from 'node:fs';
13
+ import { hostname, homedir, userInfo, totalmem, freemem, cpus, platform, arch, release } from 'node:os';
14
+ // ── Cache ──
15
+ let cached = null;
16
+ // ── Helpers ──
17
+ function exec(cmd, timeoutMs = 3000) {
18
+ try {
19
+ return execSync(cmd, { encoding: 'utf-8', timeout: timeoutMs, stdio: ['pipe', 'pipe', 'pipe'] }).trim();
20
+ }
21
+ catch {
22
+ return '';
23
+ }
24
+ }
25
+ function parseBytes(str) {
26
+ const match = str.match(/([\d.]+)\s*(B|KB|MB|GB|TB|Ki|Mi|Gi|Ti)/i);
27
+ if (!match)
28
+ return 0;
29
+ const val = parseFloat(match[1]);
30
+ const unit = match[2].toUpperCase();
31
+ const multipliers = {
32
+ 'B': 1, 'KB': 1024, 'MB': 1024 ** 2, 'GB': 1024 ** 3, 'TB': 1024 ** 4,
33
+ 'KI': 1024, 'MI': 1024 ** 2, 'GI': 1024 ** 3, 'TI': 1024 ** 4,
34
+ };
35
+ return val * (multipliers[unit] || 1);
36
+ }
37
+ function formatBytes(bytes) {
38
+ if (bytes >= 1024 ** 4)
39
+ return `${(bytes / 1024 ** 4).toFixed(1)} TB`;
40
+ if (bytes >= 1024 ** 3)
41
+ return `${(bytes / 1024 ** 3).toFixed(1)} GB`;
42
+ if (bytes >= 1024 ** 2)
43
+ return `${(bytes / 1024 ** 2).toFixed(0)} MB`;
44
+ if (bytes >= 1024)
45
+ return `${(bytes / 1024).toFixed(0)} KB`;
46
+ return `${bytes} B`;
47
+ }
48
+ function formatUptime(seconds) {
49
+ const days = Math.floor(seconds / 86400);
50
+ const hours = Math.floor((seconds % 86400) / 3600);
51
+ const mins = Math.floor((seconds % 3600) / 60);
52
+ const parts = [];
53
+ if (days > 0)
54
+ parts.push(`${days}d`);
55
+ if (hours > 0)
56
+ parts.push(`${hours}h`);
57
+ if (mins > 0)
58
+ parts.push(`${mins}m`);
59
+ return parts.join(' ') || '<1m';
60
+ }
61
+ // ── macOS Probes ──
62
+ function probeMacHardware() {
63
+ const raw = exec('system_profiler SPHardwareDataType', 5000);
64
+ if (!raw)
65
+ return {};
66
+ const get = (label) => {
67
+ const match = raw.match(new RegExp(`${label}:\\s*(.+)`, 'i'));
68
+ return match ? match[1].trim() : '';
69
+ };
70
+ const coresMatch = get('Total Number of Cores').match(/(\d+)\s*\((\d+)\s*Performance.*?(\d+)\s*Efficiency\)/);
71
+ return {
72
+ model: get('Model Name') || undefined,
73
+ modelId: get('Model Identifier') || undefined,
74
+ chip: get('Chip') || undefined,
75
+ totalCores: coresMatch ? parseInt(coresMatch[1]) : parseInt(get('Total Number of Cores')) || undefined,
76
+ perfCores: coresMatch ? parseInt(coresMatch[2]) : undefined,
77
+ effCores: coresMatch ? parseInt(coresMatch[3]) : undefined,
78
+ memoryGB: parseInt(get('Memory')) || undefined,
79
+ };
80
+ }
81
+ function probeMacGpu() {
82
+ const raw = exec('system_profiler SPDisplaysDataType', 5000);
83
+ if (!raw)
84
+ return [];
85
+ const gpus = [];
86
+ // Split by GPU entries — each starts with a chipset name followed by a colon at 4-space indent
87
+ const sections = raw.split(/\n (?=\S.*:)/).filter(s => s.includes('Chipset Model') || s.includes('Vendor'));
88
+ // Simpler: extract all GPU blocks
89
+ const chipsetMatches = raw.match(/Chipset Model:\s*(.+)/g) || [];
90
+ const coreMatches = raw.match(/Total Number of Cores:\s*(\d+)/g) || [];
91
+ const metalMatches = raw.match(/Metal Support:\s*(.+)/g) || [];
92
+ for (let i = 0; i < chipsetMatches.length; i++) {
93
+ const model = chipsetMatches[i]?.replace('Chipset Model:', '').trim() || 'Unknown';
94
+ const cores = coreMatches[i] ? parseInt(coreMatches[i].replace(/\D/g, '')) : undefined;
95
+ const metal = metalMatches[i]?.replace('Metal Support:', '').trim() || undefined;
96
+ gpus.push({ model, cores, metal });
97
+ }
98
+ return gpus.length > 0 ? gpus : [{ model: 'Unknown' }];
99
+ }
100
+ function probeMacDisplays() {
101
+ const raw = exec('system_profiler SPDisplaysDataType', 5000);
102
+ if (!raw)
103
+ return [];
104
+ const displays = [];
105
+ const displayBlocks = raw.split(/\n (?=\S.*:)/);
106
+ for (const block of displayBlocks) {
107
+ const nameMatch = block.match(/^\s*(.+?):\s*$/m);
108
+ const resMatch = block.match(/Resolution:\s*(.+)/i);
109
+ const typeMatch = block.match(/Display Type:\s*(.+)/i);
110
+ const mainMatch = block.match(/Main Display:\s*(Yes)/i);
111
+ if (resMatch) {
112
+ displays.push({
113
+ name: nameMatch ? nameMatch[1].trim() : 'Display',
114
+ resolution: resMatch[1].trim(),
115
+ type: typeMatch ? typeMatch[1].trim() : undefined,
116
+ main: !!mainMatch,
117
+ });
118
+ }
119
+ }
120
+ return displays;
121
+ }
122
+ function probeMacBattery() {
123
+ const raw = exec('pmset -g batt');
124
+ if (!raw)
125
+ return { present: false };
126
+ const percentMatch = raw.match(/(\d+)%/);
127
+ const chargingMatch = raw.match(/(charging|discharging|charged|AC Power)/i);
128
+ const timeMatch = raw.match(/([\d:]+)\s*remaining/);
129
+ if (!percentMatch)
130
+ return { present: false };
131
+ return {
132
+ present: true,
133
+ percent: parseInt(percentMatch[1]),
134
+ charging: chargingMatch ? /charging|AC Power/i.test(chargingMatch[1]) && !/discharging/i.test(chargingMatch[1]) : undefined,
135
+ timeRemaining: timeMatch ? timeMatch[1] : undefined,
136
+ };
137
+ }
138
+ function probeMacNetwork() {
139
+ const wifi = exec('networksetup -getairportnetwork en0');
140
+ const wifiName = wifi.match(/Current Wi-Fi Network:\s*(.+)/i)?.[1] ||
141
+ (wifi.includes('not associated') ? 'not connected' : undefined);
142
+ const ip = exec("ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null");
143
+ return { wifi: wifiName, localIp: ip || undefined };
144
+ }
145
+ function probeMacOs() {
146
+ const productName = exec('sw_vers -productName') || 'macOS';
147
+ const productVersion = exec('sw_vers -productVersion') || 'unknown';
148
+ return {
149
+ os: `${productName} ${productVersion}`,
150
+ osVersion: productVersion,
151
+ };
152
+ }
153
+ // ── Linux Probes ──
154
+ function probeLinuxCpu() {
155
+ const model = exec("grep -m1 'model name' /proc/cpuinfo")?.split(':')?.[1]?.trim() || 'Unknown';
156
+ const cores = parseInt(exec('nproc') || '0') || cpus().length;
157
+ return { model, cores, arch: arch() };
158
+ }
159
+ function probeLinuxGpu() {
160
+ const lspci = exec('lspci 2>/dev/null | grep -iE "VGA|3D|Display"');
161
+ if (!lspci)
162
+ return [{ model: 'Unknown' }];
163
+ const gpus = [];
164
+ for (const line of lspci.split('\n')) {
165
+ const match = line.match(/:\s*(.+)/);
166
+ if (match) {
167
+ const model = match[1].trim();
168
+ const cuda = /nvidia/i.test(model);
169
+ gpus.push({ model, cuda });
170
+ }
171
+ }
172
+ // Check for NVIDIA driver
173
+ const nvidiaSmi = exec('nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null');
174
+ if (nvidiaSmi && gpus.length > 0) {
175
+ gpus[0].driver = nvidiaSmi.split('\n')[0];
176
+ gpus[0].cuda = true;
177
+ // Get VRAM
178
+ const vram = exec('nvidia-smi --query-gpu=memory.total --format=csv,noheader 2>/dev/null');
179
+ if (vram)
180
+ gpus[0].vram = vram.split('\n')[0].trim();
181
+ }
182
+ return gpus.length > 0 ? gpus : [{ model: 'Unknown' }];
183
+ }
184
+ function probeLinuxDisplays() {
185
+ const xrandr = exec('xrandr --current 2>/dev/null');
186
+ if (!xrandr)
187
+ return [];
188
+ const displays = [];
189
+ const lines = xrandr.split('\n');
190
+ for (const line of lines) {
191
+ const match = line.match(/^(\S+)\s+connected\s+(primary\s+)?(\d+x\d+)/);
192
+ if (match) {
193
+ displays.push({
194
+ name: match[1],
195
+ resolution: match[3],
196
+ main: !!match[2],
197
+ });
198
+ }
199
+ }
200
+ return displays;
201
+ }
202
+ function probeLinuxBattery() {
203
+ const capacityPath = '/sys/class/power_supply/BAT0/capacity';
204
+ const statusPath = '/sys/class/power_supply/BAT0/status';
205
+ if (!existsSync(capacityPath))
206
+ return { present: false };
207
+ try {
208
+ const percent = parseInt(readFileSync(capacityPath, 'utf-8').trim());
209
+ const status = existsSync(statusPath) ? readFileSync(statusPath, 'utf-8').trim() : '';
210
+ return {
211
+ present: true,
212
+ percent,
213
+ charging: status === 'Charging',
214
+ };
215
+ }
216
+ catch {
217
+ return { present: false };
218
+ }
219
+ }
220
+ function probeLinuxNetwork() {
221
+ const wifi = exec('iwgetid -r 2>/dev/null') || exec('nmcli -t -f active,ssid dev wifi 2>/dev/null | grep "^yes"')?.split(':')?.[1];
222
+ const ip = exec("hostname -I 2>/dev/null")?.split(' ')[0];
223
+ return {
224
+ wifi: wifi || 'not connected',
225
+ localIp: ip || undefined,
226
+ };
227
+ }
228
+ function probeLinuxOs() {
229
+ const prettyName = exec("grep PRETTY_NAME /etc/os-release 2>/dev/null")?.replace(/PRETTY_NAME=["']?/, '').replace(/["']$/, '') || 'Linux';
230
+ const version = exec("grep VERSION_ID /etc/os-release 2>/dev/null")?.replace(/VERSION_ID=["']?/, '').replace(/["']$/, '') || release();
231
+ return { os: prettyName, osVersion: version };
232
+ }
233
+ // ── Disk ──
234
+ function probeDisk() {
235
+ if (platform() === 'darwin') {
236
+ const raw = exec('df -h /');
237
+ const line = raw.split('\n')[1];
238
+ if (line) {
239
+ const parts = line.split(/\s+/);
240
+ return {
241
+ filesystem: parts[0] || '/',
242
+ total: parts[1] || 'unknown',
243
+ used: parts[2] || 'unknown',
244
+ available: parts[3] || 'unknown',
245
+ usedPercent: parseInt(parts[4]) || 0,
246
+ };
247
+ }
248
+ }
249
+ else {
250
+ const raw = exec('df -h / 2>/dev/null');
251
+ const line = raw.split('\n')[1];
252
+ if (line) {
253
+ const parts = line.split(/\s+/);
254
+ return {
255
+ filesystem: parts[0] || '/',
256
+ total: parts[1] || 'unknown',
257
+ used: parts[2] || 'unknown',
258
+ available: parts[3] || 'unknown',
259
+ usedPercent: parseInt(parts[4]) || 0,
260
+ };
261
+ }
262
+ }
263
+ return { filesystem: '/', total: 'unknown', available: 'unknown', used: 'unknown', usedPercent: 0 };
264
+ }
265
+ // ── Dev Tools ──
266
+ function probeDevTools() {
267
+ const tools = [];
268
+ const checks = [
269
+ { name: 'Node.js', cmd: 'node -v' },
270
+ { name: 'npm', cmd: 'npm -v', parse: v => `v${v}` },
271
+ { name: 'Python', cmd: 'python3 --version', parse: v => v.replace('Python ', 'v') },
272
+ { name: 'Git', cmd: 'git --version', parse: v => v.replace('git version ', 'v').split(' ')[0] },
273
+ { name: 'Docker', cmd: 'docker --version', parse: v => 'v' + (v.match(/(\d+\.\d+\.\d+)/)?.[1] || v) },
274
+ { name: 'Homebrew', cmd: 'brew --version', parse: v => 'v' + (v.match(/(\d+\.\d+\.\d+)/)?.[1] || v) },
275
+ { name: 'Rust', cmd: 'rustc --version', parse: v => 'v' + (v.match(/(\d+\.\d+\.\d+)/)?.[1] || v) },
276
+ { name: 'Go', cmd: 'go version', parse: v => v.match(/go(\d+\.\d+\.\d+)/)?.[0] || v },
277
+ { name: 'Deno', cmd: 'deno --version', parse: v => 'v' + (v.match(/deno\s+(\d+\.\d+\.\d+)/)?.[1] || v) },
278
+ { name: 'Bun', cmd: 'bun --version', parse: v => `v${v}` },
279
+ { name: 'pnpm', cmd: 'pnpm --version', parse: v => `v${v}` },
280
+ { name: 'Supabase CLI', cmd: 'npx supabase --version 2>/dev/null', parse: v => `v${v}` },
281
+ { name: 'Xcode', cmd: 'xcodebuild -version 2>/dev/null', parse: v => v.split('\n')[0]?.replace('Xcode ', 'v') || v },
282
+ { name: 'Swift', cmd: 'swift --version 2>/dev/null', parse: v => 'v' + (v.match(/(\d+\.\d+(\.\d+)?)/)?.[1] || v) },
283
+ { name: 'FFmpeg', cmd: 'ffmpeg -version 2>/dev/null', parse: v => 'v' + (v.match(/version\s+(\S+)/)?.[1] || v) },
284
+ { name: 'Ollama', cmd: 'ollama --version 2>/dev/null', parse: v => 'v' + (v.match(/(\d+\.\d+\.\d+)/)?.[1] || v) },
285
+ ];
286
+ for (const { name, cmd, parse } of checks) {
287
+ const raw = exec(cmd, 2000);
288
+ if (raw && !raw.includes('not found') && !raw.includes('No such file')) {
289
+ const version = parse ? parse(raw) : raw;
290
+ tools.push({ name, version });
291
+ }
292
+ }
293
+ return tools;
294
+ }
295
+ // ── Memory pressure ──
296
+ function getMemoryPressure(freeBytes, totalBytes) {
297
+ const freePercent = freeBytes / totalBytes;
298
+ if (freePercent > 0.25)
299
+ return 'low';
300
+ if (freePercent > 0.10)
301
+ return 'moderate';
302
+ return 'high';
303
+ }
304
+ // ── GPU acceleration detection ──
305
+ function detectGpuAcceleration(gpus) {
306
+ if (platform() === 'darwin') {
307
+ if (gpus.some(g => g.metal))
308
+ return 'metal';
309
+ }
310
+ if (gpus.some(g => g.cuda))
311
+ return 'cuda';
312
+ // Check for Vulkan support on Linux
313
+ if (platform() === 'linux' && exec('vulkaninfo --summary 2>/dev/null'))
314
+ return 'vulkan';
315
+ return 'cpu-only';
316
+ }
317
+ // ── Model size recommendation ──
318
+ function recommendModelSize(totalMemoryGB, gpuAccel) {
319
+ // Conservative: leave room for OS + apps
320
+ const availableForModel = totalMemoryGB * 0.6;
321
+ if (availableForModel >= 40)
322
+ return '70B';
323
+ if (availableForModel >= 20)
324
+ return '34B';
325
+ if (availableForModel >= 12)
326
+ return '14B';
327
+ if (availableForModel >= 6)
328
+ return '7B';
329
+ if (availableForModel >= 3)
330
+ return '3B';
331
+ return '1B';
332
+ }
333
+ // ── Main Probe ──
334
+ export async function probeMachine() {
335
+ if (cached)
336
+ return cached;
337
+ const plat = platform();
338
+ const totalBytes = totalmem();
339
+ const freeBytes = freemem();
340
+ const usedBytes = totalBytes - freeBytes;
341
+ const totalGB = totalBytes / (1024 ** 3);
342
+ let cpu;
343
+ let gpus;
344
+ let displays;
345
+ let battery;
346
+ let net;
347
+ let osInfo;
348
+ let model;
349
+ let modelId;
350
+ if (plat === 'darwin') {
351
+ const hw = probeMacHardware();
352
+ cpu = {
353
+ model: hw.chip || cpus()[0]?.model || 'Unknown',
354
+ chip: hw.chip,
355
+ cores: hw.totalCores || cpus().length,
356
+ performanceCores: hw.perfCores,
357
+ efficiencyCores: hw.effCores,
358
+ arch: arch(),
359
+ };
360
+ model = hw.model;
361
+ modelId = hw.modelId;
362
+ gpus = probeMacGpu();
363
+ displays = probeMacDisplays();
364
+ battery = probeMacBattery();
365
+ net = probeMacNetwork();
366
+ osInfo = probeMacOs();
367
+ }
368
+ else {
369
+ cpu = probeLinuxCpu();
370
+ gpus = probeLinuxGpu();
371
+ displays = probeLinuxDisplays();
372
+ battery = probeLinuxBattery();
373
+ net = probeLinuxNetwork();
374
+ osInfo = probeLinuxOs();
375
+ }
376
+ const gpuAccel = detectGpuAcceleration(gpus);
377
+ const devTools = probeDevTools();
378
+ // Uptime
379
+ const uptimeSeconds = plat === 'darwin'
380
+ ? (() => {
381
+ const bootTime = exec("sysctl -n kern.boottime");
382
+ const match = bootTime.match(/sec\s*=\s*(\d+)/);
383
+ return match ? Math.floor(Date.now() / 1000) - parseInt(match[1]) : 0;
384
+ })()
385
+ : (() => {
386
+ const raw = exec('cat /proc/uptime 2>/dev/null');
387
+ return raw ? Math.floor(parseFloat(raw.split(' ')[0])) : 0;
388
+ })();
389
+ const profile = {
390
+ model,
391
+ modelId,
392
+ cpu,
393
+ gpu: gpus,
394
+ memory: {
395
+ total: formatBytes(totalBytes),
396
+ totalBytes,
397
+ free: formatBytes(freeBytes),
398
+ freeBytes,
399
+ used: formatBytes(usedBytes),
400
+ usedBytes,
401
+ pressure: getMemoryPressure(freeBytes, totalBytes),
402
+ },
403
+ disk: probeDisk(),
404
+ os: osInfo.os,
405
+ osVersion: osInfo.osVersion,
406
+ kernel: release(),
407
+ platform: plat,
408
+ uptime: formatUptime(uptimeSeconds),
409
+ displays,
410
+ battery,
411
+ network: {
412
+ hostname: hostname(),
413
+ wifi: net.wifi,
414
+ localIp: net.localIp,
415
+ },
416
+ shell: process.env.SHELL || 'unknown',
417
+ user: userInfo().username,
418
+ home: homedir(),
419
+ devTools,
420
+ canRunLocalModels: gpuAccel !== 'cpu-only' || totalGB >= 8,
421
+ gpuAcceleration: gpuAccel,
422
+ recommendedModelSize: recommendModelSize(totalGB, gpuAccel),
423
+ probedAt: new Date().toISOString(),
424
+ };
425
+ cached = profile;
426
+ return profile;
427
+ }
428
+ /** Get the cached profile (null if probeMachine hasn't been called) */
429
+ export function getMachineProfile() {
430
+ return cached;
431
+ }
432
+ /** Force a fresh probe (clears cache) */
433
+ export async function reprobeMachine() {
434
+ cached = null;
435
+ return probeMachine();
436
+ }
437
+ // ── Formatted output (for `kbot machine` command) ──
438
+ export function formatMachineProfile(p) {
439
+ const lines = [];
440
+ // Header
441
+ lines.push('');
442
+ lines.push(` ${p.model || 'Machine'}${p.modelId ? ` (${p.modelId})` : ''}`);
443
+ lines.push(` ${'─'.repeat(54)}`);
444
+ // Hardware
445
+ lines.push('');
446
+ lines.push(' Hardware');
447
+ lines.push(` CPU ${p.cpu.model}`);
448
+ if (p.cpu.performanceCores) {
449
+ lines.push(` Cores ${p.cpu.cores} (${p.cpu.performanceCores}P + ${p.cpu.efficiencyCores}E)`);
450
+ }
451
+ else {
452
+ lines.push(` Cores ${p.cpu.cores}`);
453
+ }
454
+ lines.push(` Arch ${p.cpu.arch}`);
455
+ for (const gpu of p.gpu) {
456
+ lines.push(` GPU ${gpu.model}${gpu.cores ? ` (${gpu.cores} cores)` : ''}`);
457
+ if (gpu.metal)
458
+ lines.push(` Metal ${gpu.metal}`);
459
+ if (gpu.cuda)
460
+ lines.push(` CUDA yes${gpu.driver ? ` (driver ${gpu.driver})` : ''}`);
461
+ if (gpu.vram)
462
+ lines.push(` VRAM ${gpu.vram}`);
463
+ }
464
+ lines.push(` Memory ${p.memory.total} (${p.memory.free} free, pressure: ${p.memory.pressure})`);
465
+ lines.push(` Disk ${p.disk.total} total, ${p.disk.available} available (${p.disk.usedPercent}% used)`);
466
+ // Displays
467
+ if (p.displays.length > 0) {
468
+ lines.push('');
469
+ lines.push(' Displays');
470
+ for (const d of p.displays) {
471
+ lines.push(` ${d.name} ${d.resolution}${d.type ? ` — ${d.type}` : ''}${d.main ? ' (main)' : ''}`);
472
+ }
473
+ }
474
+ // OS
475
+ lines.push('');
476
+ lines.push(' System');
477
+ lines.push(` OS ${p.os}`);
478
+ lines.push(` Kernel ${p.kernel}`);
479
+ lines.push(` Uptime ${p.uptime}`);
480
+ lines.push(` Shell ${p.shell.split('/').pop()}`);
481
+ lines.push(` User ${p.user} (${p.home})`);
482
+ // Battery
483
+ if (p.battery.present) {
484
+ const status = p.battery.charging ? 'charging' : 'discharging';
485
+ const time = p.battery.timeRemaining ? `, ${p.battery.timeRemaining} remaining` : '';
486
+ lines.push(` Battery ${p.battery.percent}% ${status}${time}`);
487
+ }
488
+ // Network
489
+ lines.push(` Hostname ${p.network.hostname}`);
490
+ if (p.network.wifi)
491
+ lines.push(` WiFi ${p.network.wifi}`);
492
+ if (p.network.localIp)
493
+ lines.push(` Local IP ${p.network.localIp}`);
494
+ // Dev tools
495
+ if (p.devTools.length > 0) {
496
+ lines.push('');
497
+ lines.push(' Dev Tools');
498
+ // Two-column layout
499
+ const maxNameLen = Math.max(...p.devTools.map(t => t.name.length));
500
+ for (const tool of p.devTools) {
501
+ lines.push(` ${tool.name.padEnd(maxNameLen + 2)}${tool.version}`);
502
+ }
503
+ }
504
+ // AI capabilities
505
+ lines.push('');
506
+ lines.push(' AI Capabilities');
507
+ lines.push(` Acceleration ${p.gpuAcceleration}`);
508
+ lines.push(` Local models ${p.canRunLocalModels ? 'yes' : 'no'}`);
509
+ lines.push(` Recommended up to ${p.recommendedModelSize} parameters`);
510
+ lines.push('');
511
+ lines.push(` ${'─'.repeat(54)}`);
512
+ lines.push(` Probed at ${p.probedAt}`);
513
+ lines.push('');
514
+ return lines.join('\n');
515
+ }
516
+ // ── Compact format for system prompt injection ──
517
+ export function formatMachineForPrompt(p) {
518
+ const parts = ['[Machine Context]'];
519
+ parts.push(`Machine: ${p.model || 'Unknown'}${p.cpu.chip ? ` — ${p.cpu.chip}` : ` — ${p.cpu.model}`}`);
520
+ parts.push(`CPU: ${p.cpu.cores} cores${p.cpu.performanceCores ? ` (${p.cpu.performanceCores}P + ${p.cpu.efficiencyCores}E)` : ''}, ${p.cpu.arch}`);
521
+ const gpuSummary = p.gpu.map(g => `${g.model}${g.cores ? ` (${g.cores} cores)` : ''}`).join(', ');
522
+ parts.push(`GPU: ${gpuSummary}`);
523
+ parts.push(`Memory: ${p.memory.total} (${p.memory.free} free, ${p.memory.pressure} pressure)`);
524
+ parts.push(`Disk: ${p.disk.available} available of ${p.disk.total}`);
525
+ parts.push(`OS: ${p.os} (${p.kernel})`);
526
+ if (p.displays.length > 0) {
527
+ parts.push(`Display: ${p.displays.map(d => `${d.resolution}${d.type ? ` ${d.type}` : ''}`).join(', ')}`);
528
+ }
529
+ if (p.battery.present) {
530
+ parts.push(`Battery: ${p.battery.percent}% ${p.battery.charging ? 'charging' : 'discharging'}`);
531
+ }
532
+ parts.push(`GPU accel: ${p.gpuAcceleration} — local models up to ${p.recommendedModelSize}`);
533
+ const toolNames = p.devTools.map(t => `${t.name} ${t.version}`).join(', ');
534
+ if (toolNames)
535
+ parts.push(`Tools: ${toolNames}`);
536
+ return parts.join('\n');
537
+ }
538
+ //# sourceMappingURL=machine.js.map