@benzsiangco/jarvis 1.0.0 → 1.1.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 (55) hide show
  1. package/README.md +5 -0
  2. package/bin/{jarvis.js → jarvis} +1 -1
  3. package/dist/cli.js +476 -350
  4. package/dist/electron/main.js +160 -0
  5. package/dist/electron/preload.js +19 -0
  6. package/package.json +21 -8
  7. package/skills.md +147 -0
  8. package/src/agents/index.ts +248 -0
  9. package/src/brain/loader.ts +136 -0
  10. package/src/cli.ts +411 -0
  11. package/src/config/index.ts +363 -0
  12. package/src/core/executor.ts +222 -0
  13. package/src/core/plugins.ts +148 -0
  14. package/src/core/types.ts +217 -0
  15. package/src/electron/main.ts +192 -0
  16. package/src/electron/preload.ts +25 -0
  17. package/src/electron/types.d.ts +20 -0
  18. package/src/index.ts +12 -0
  19. package/src/providers/antigravity-loader.ts +233 -0
  20. package/src/providers/antigravity.ts +585 -0
  21. package/src/providers/index.ts +523 -0
  22. package/src/sessions/index.ts +194 -0
  23. package/src/tools/index.ts +436 -0
  24. package/src/tui/index.tsx +784 -0
  25. package/src/utils/auth-prompt.ts +394 -0
  26. package/src/utils/index.ts +180 -0
  27. package/src/utils/native-picker.ts +71 -0
  28. package/src/utils/skills.ts +99 -0
  29. package/src/utils/table-integration-examples.ts +617 -0
  30. package/src/utils/table-utils.ts +401 -0
  31. package/src/web/build-ui.ts +27 -0
  32. package/src/web/server.ts +674 -0
  33. package/src/web/ui/dist/.gitkeep +0 -0
  34. package/src/web/ui/dist/main.css +1 -0
  35. package/src/web/ui/dist/main.js +320 -0
  36. package/src/web/ui/dist/main.js.map +20 -0
  37. package/src/web/ui/index.html +46 -0
  38. package/src/web/ui/src/App.tsx +143 -0
  39. package/src/web/ui/src/Modules/Safety/GuardianModal.tsx +83 -0
  40. package/src/web/ui/src/components/Layout/ContextPanel.tsx +243 -0
  41. package/src/web/ui/src/components/Layout/Header.tsx +91 -0
  42. package/src/web/ui/src/components/Layout/ModelSelector.tsx +235 -0
  43. package/src/web/ui/src/components/Layout/SessionStats.tsx +369 -0
  44. package/src/web/ui/src/components/Layout/Sidebar.tsx +895 -0
  45. package/src/web/ui/src/components/Modules/Chat/ChatStage.tsx +620 -0
  46. package/src/web/ui/src/components/Modules/Chat/MessageItem.tsx +446 -0
  47. package/src/web/ui/src/components/Modules/Editor/CommandInspector.tsx +71 -0
  48. package/src/web/ui/src/components/Modules/Editor/DiffViewer.tsx +83 -0
  49. package/src/web/ui/src/components/Modules/Terminal/TabbedTerminal.tsx +202 -0
  50. package/src/web/ui/src/components/Settings/SettingsModal.tsx +935 -0
  51. package/src/web/ui/src/config/models.ts +70 -0
  52. package/src/web/ui/src/main.tsx +13 -0
  53. package/src/web/ui/src/store/agentStore.ts +41 -0
  54. package/src/web/ui/src/store/uiStore.ts +64 -0
  55. package/src/web/ui/src/types/index.ts +54 -0
@@ -0,0 +1,401 @@
1
+ /**
2
+ * Table Utilities for Jarvis Project
3
+ * Helper functions for creating and formatting tables
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+
8
+ // ============================================
9
+ // Terminal Table Utilities
10
+ // ============================================
11
+
12
+ export interface TableColumn {
13
+ key: string;
14
+ header: string;
15
+ width?: number;
16
+ align?: 'left' | 'center' | 'right';
17
+ color?: (value: any) => string;
18
+ }
19
+
20
+ export class TerminalTable {
21
+ private columns: TableColumn[];
22
+ private rows: any[] = [];
23
+
24
+ constructor(columns: TableColumn[]) {
25
+ this.columns = columns;
26
+ }
27
+
28
+ addRow(row: any) {
29
+ this.rows.push(row);
30
+ }
31
+
32
+ addRows(rows: any[]) {
33
+ this.rows.push(...rows);
34
+ }
35
+
36
+ private calculateColumnWidths(): number[] {
37
+ return this.columns.map((col, i) => {
38
+ if (col.width) return col.width;
39
+
40
+ const headerWidth = col.header.length;
41
+ const maxContentWidth = Math.max(
42
+ ...this.rows.map(row => String(row[col.key] || '').length),
43
+ 0
44
+ );
45
+
46
+ return Math.max(headerWidth, maxContentWidth) + 2;
47
+ });
48
+ }
49
+
50
+ private formatCell(value: string, width: number, align: 'left' | 'center' | 'right' = 'left'): string {
51
+ const strValue = String(value);
52
+ const padding = width - strValue.length;
53
+
54
+ if (padding <= 0) return strValue.slice(0, width);
55
+
56
+ switch (align) {
57
+ case 'center':
58
+ const leftPad = Math.floor(padding / 2);
59
+ const rightPad = padding - leftPad;
60
+ return ' '.repeat(leftPad) + strValue + ' '.repeat(rightPad);
61
+ case 'right':
62
+ return ' '.repeat(padding) + strValue;
63
+ default:
64
+ return strValue + ' '.repeat(padding);
65
+ }
66
+ }
67
+
68
+ render(): string {
69
+ const widths = this.calculateColumnWidths();
70
+ const lines: string[] = [];
71
+
72
+ // Top border
73
+ lines.push('ā”Œ' + widths.map(w => '─'.repeat(w)).join('┬') + '┐');
74
+
75
+ // Header
76
+ const headerCells = this.columns.map((col, i) =>
77
+ chalk.bold.cyan(this.formatCell(col.header, widths[i], 'center'))
78
+ );
79
+ lines.push('│' + headerCells.join('│') + '│');
80
+
81
+ // Header separator
82
+ lines.push('ā”œ' + widths.map(w => '─'.repeat(w)).join('┼') + '┤');
83
+
84
+ // Rows
85
+ this.rows.forEach((row, rowIndex) => {
86
+ const cells = this.columns.map((col, i) => {
87
+ const value = row[col.key] || '';
88
+ const formatted = this.formatCell(String(value), widths[i], col.align);
89
+
90
+ // Apply color if specified
91
+ if (col.color) {
92
+ return col.color(value);
93
+ }
94
+
95
+ // Alternate row colors for better readability
96
+ return rowIndex % 2 === 0 ? formatted : chalk.dim(formatted);
97
+ });
98
+
99
+ lines.push('│' + cells.join('│') + '│');
100
+ });
101
+
102
+ // Bottom border
103
+ lines.push('ā””' + widths.map(w => '─'.repeat(w)).join('┓') + 'ā”˜');
104
+
105
+ return lines.join('\n');
106
+ }
107
+
108
+ print() {
109
+ console.log(this.render());
110
+ }
111
+ }
112
+
113
+ // ============================================
114
+ // Quick Table Functions
115
+ // ============================================
116
+
117
+ /**
118
+ * Create a simple table from array of objects
119
+ */
120
+ export function createTable(data: any[], columns?: string[]): TerminalTable {
121
+ if (data.length === 0) {
122
+ throw new Error('Cannot create table from empty data');
123
+ }
124
+
125
+ const keys = columns || Object.keys(data[0]);
126
+ const tableColumns: TableColumn[] = keys.map(key => ({
127
+ key,
128
+ header: key.toUpperCase().replace(/_/g, ' '),
129
+ }));
130
+
131
+ const table = new TerminalTable(tableColumns);
132
+ table.addRows(data);
133
+ return table;
134
+ }
135
+
136
+ /**
137
+ * Create a comparison table
138
+ */
139
+ export function createComparisonTable(
140
+ items: any[],
141
+ attributes: string[]
142
+ ): TerminalTable {
143
+ const columns: TableColumn[] = [
144
+ { key: 'attribute', header: 'Attribute', align: 'left' },
145
+ ...items.map((item, i) => ({
146
+ key: `item${i}`,
147
+ header: item.name || `Item ${i + 1}`,
148
+ align: 'center' as const,
149
+ })),
150
+ ];
151
+
152
+ const table = new TerminalTable(columns);
153
+
154
+ attributes.forEach(attr => {
155
+ const row: any = { attribute: attr };
156
+ items.forEach((item, i) => {
157
+ row[`item${i}`] = item[attr] || '-';
158
+ });
159
+ table.addRow(row);
160
+ });
161
+
162
+ return table;
163
+ }
164
+
165
+ /**
166
+ * Create a status table with colored status indicators
167
+ */
168
+ export function createStatusTable(services: Array<{
169
+ name: string;
170
+ status: 'online' | 'degraded' | 'offline';
171
+ [key: string]: any;
172
+ }>): TerminalTable {
173
+ const statusColors = {
174
+ online: (text: string) => chalk.green('🟢 ' + text),
175
+ degraded: (text: string) => chalk.yellow('🟔 ' + text),
176
+ offline: (text: string) => chalk.red('šŸ”“ ' + text),
177
+ };
178
+
179
+ const keys = Object.keys(services[0]).filter(k => k !== 'status');
180
+ const columns: TableColumn[] = [
181
+ ...keys.map(key => ({
182
+ key,
183
+ header: key.toUpperCase(),
184
+ })),
185
+ {
186
+ key: 'status',
187
+ header: 'STATUS',
188
+ align: 'center' as const,
189
+ color: (value: any) => statusColors[value as keyof typeof statusColors]?.(value) || value,
190
+ },
191
+ ];
192
+
193
+ const table = new TerminalTable(columns);
194
+ table.addRows(services);
195
+ return table;
196
+ }
197
+
198
+ // ============================================
199
+ // Data Formatters
200
+ // ============================================
201
+
202
+ export const formatters = {
203
+ /**
204
+ * Format bytes to human-readable size
205
+ */
206
+ bytes: (bytes: number): string => {
207
+ if (bytes === 0) return '0 B';
208
+ const k = 1024;
209
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
210
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
211
+ return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
212
+ },
213
+
214
+ /**
215
+ * Format milliseconds to human-readable duration
216
+ */
217
+ duration: (ms: number): string => {
218
+ if (ms < 1000) return `${ms}ms`;
219
+ if (ms < 60000) return `${(ms / 1000).toFixed(2)}s`;
220
+ if (ms < 3600000) return `${Math.floor(ms / 60000)}m ${Math.floor((ms % 60000) / 1000)}s`;
221
+ return `${Math.floor(ms / 3600000)}h ${Math.floor((ms % 3600000) / 60000)}m`;
222
+ },
223
+
224
+ /**
225
+ * Format number as currency
226
+ */
227
+ currency: (amount: number, currency = 'USD'): string => {
228
+ return new Intl.NumberFormat('en-US', {
229
+ style: 'currency',
230
+ currency,
231
+ }).format(amount);
232
+ },
233
+
234
+ /**
235
+ * Format date to ISO string
236
+ */
237
+ date: (date: Date | string): string => {
238
+ const d = typeof date === 'string' ? new Date(date) : date;
239
+ return d.toISOString().split('T')[0];
240
+ },
241
+
242
+ /**
243
+ * Format date and time
244
+ */
245
+ datetime: (date: Date | string): string => {
246
+ const d = typeof date === 'string' ? new Date(date) : date;
247
+ return d.toLocaleString();
248
+ },
249
+
250
+ /**
251
+ * Format percentage
252
+ */
253
+ percent: (value: number, decimals = 1): string => {
254
+ return `${value.toFixed(decimals)}%`;
255
+ },
256
+
257
+ /**
258
+ * Format number with thousand separators
259
+ */
260
+ number: (value: number): string => {
261
+ return value.toLocaleString();
262
+ },
263
+
264
+ /**
265
+ * Truncate string with ellipsis
266
+ */
267
+ truncate: (str: string, maxLength: number): string => {
268
+ if (str.length <= maxLength) return str;
269
+ return str.slice(0, maxLength - 3) + '...';
270
+ },
271
+
272
+ /**
273
+ * Format boolean as checkmark/cross
274
+ */
275
+ boolean: (value: boolean): string => {
276
+ return value ? 'āœ“' : 'āœ—';
277
+ },
278
+ };
279
+
280
+ // ============================================
281
+ // Export to CSV
282
+ // ============================================
283
+
284
+ export function exportToCSV(data: any[], filename = 'export.csv'): string {
285
+ if (data.length === 0) return '';
286
+
287
+ const headers = Object.keys(data[0]);
288
+ const csvContent = [
289
+ headers.join(','),
290
+ ...data.map(row =>
291
+ headers.map(header => {
292
+ const value = row[header];
293
+ // Escape commas and quotes
294
+ if (typeof value === 'string' && (value.includes(',') || value.includes('"'))) {
295
+ return `"${value.replace(/"/g, '""')}"`;
296
+ }
297
+ return value;
298
+ }).join(',')
299
+ ),
300
+ ].join('\n');
301
+
302
+ return csvContent;
303
+ }
304
+
305
+ // ============================================
306
+ // Example Usage Functions
307
+ // ============================================
308
+
309
+ export function exampleUsage() {
310
+ console.log(chalk.bold.blue('\nšŸ“Š Jarvis Table Utilities Examples\n'));
311
+
312
+ // Example 1: Simple Data Table
313
+ console.log(chalk.yellow('1. Simple Data Table:'));
314
+ const users = [
315
+ { id: 1, name: 'Alice', email: 'alice@example.com', role: 'Admin' },
316
+ { id: 2, name: 'Bob', email: 'bob@example.com', role: 'User' },
317
+ { id: 3, name: 'Carol', email: 'carol@example.com', role: 'Manager' },
318
+ ];
319
+ createTable(users).print();
320
+
321
+ // Example 2: Comparison Table
322
+ console.log(chalk.yellow('\n2. Comparison Table:'));
323
+ const models = [
324
+ { name: 'GPT-4', speed: '⭐⭐⭐', cost: '$$$$', quality: '⭐⭐⭐⭐⭐' },
325
+ { name: 'Claude 3', speed: '⭐⭐⭐⭐', cost: '$$$', quality: '⭐⭐⭐⭐⭐' },
326
+ { name: 'Gemini', speed: '⭐⭐⭐⭐', cost: '$$', quality: '⭐⭐⭐⭐' },
327
+ ];
328
+ createComparisonTable(models, ['speed', 'cost', 'quality']).print();
329
+
330
+ // Example 3: Status Table
331
+ console.log(chalk.yellow('\n3. Status Table:'));
332
+ const services = [
333
+ { name: 'API Server', status: 'online' as const, uptime: '99.9%' },
334
+ { name: 'Database', status: 'online' as const, uptime: '99.8%' },
335
+ { name: 'Cache', status: 'degraded' as const, uptime: '98.5%' },
336
+ ];
337
+ createStatusTable(services).print();
338
+
339
+ // Example 4: Custom Formatted Table
340
+ console.log(chalk.yellow('\n4. Custom Formatted Table:'));
341
+ const files = [
342
+ { name: 'document.pdf', size: 1048576, modified: new Date('2024-01-15') },
343
+ { name: 'image.png', size: 524288, modified: new Date('2024-01-16') },
344
+ { name: 'video.mp4', size: 10485760, modified: new Date('2024-01-17') },
345
+ ];
346
+
347
+ const fileTable = new TerminalTable([
348
+ { key: 'name', header: 'File Name' },
349
+ { key: 'size', header: 'Size', align: 'right' },
350
+ { key: 'modified', header: 'Modified' },
351
+ ]);
352
+
353
+ fileTable.addRows(files.map(f => ({
354
+ name: f.name,
355
+ size: formatters.bytes(f.size),
356
+ modified: formatters.date(f.modified),
357
+ })));
358
+
359
+ fileTable.print();
360
+
361
+ console.log(chalk.green('\n✨ Examples Complete!\n'));
362
+ }
363
+
364
+ // ============================================
365
+ // Performance Metrics Table
366
+ // ============================================
367
+
368
+ export function createMetricsTable(metrics: Array<{
369
+ metric: string;
370
+ value: number;
371
+ unit: string;
372
+ threshold?: number;
373
+ }>): TerminalTable {
374
+ const table = new TerminalTable([
375
+ { key: 'metric', header: 'Metric' },
376
+ { key: 'value', header: 'Value', align: 'right' },
377
+ { key: 'unit', header: 'Unit' },
378
+ { key: 'status', header: 'Status', align: 'center' },
379
+ ]);
380
+
381
+ table.addRows(metrics.map(m => {
382
+ let status = 'āœ“';
383
+ if (m.threshold && m.value > m.threshold) {
384
+ status = chalk.yellow('⚠');
385
+ }
386
+
387
+ return {
388
+ metric: m.metric,
389
+ value: m.value,
390
+ unit: m.unit,
391
+ status,
392
+ };
393
+ }));
394
+
395
+ return table;
396
+ }
397
+
398
+ // Run examples if this file is executed directly
399
+ if (import.meta.main) {
400
+ exampleUsage();
401
+ }
@@ -0,0 +1,27 @@
1
+ import { build } from 'bun';
2
+
3
+ async function buildUI() {
4
+ console.log('Building Web UI...');
5
+
6
+ const result = await build({
7
+ entrypoints: ['./src/web/ui/src/main.tsx'],
8
+ outdir: './src/web/ui/dist',
9
+ minify: true,
10
+ target: 'browser',
11
+ sourcemap: 'none',
12
+ naming: '[name].[ext]',
13
+ plugins: [],
14
+ });
15
+
16
+ if (!result.success) {
17
+ console.error('Build failed');
18
+ for (const message of result.logs) {
19
+ console.error(message);
20
+ }
21
+ process.exit(1);
22
+ }
23
+
24
+ console.log('Build successful!');
25
+ }
26
+
27
+ buildUI();