grokcodecli 0.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.
- package/.claude/settings.local.json +32 -0
- package/README.md +1464 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +61 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/loader.d.ts +34 -0
- package/dist/commands/loader.d.ts.map +1 -0
- package/dist/commands/loader.js +192 -0
- package/dist/commands/loader.js.map +1 -0
- package/dist/config/manager.d.ts +21 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +203 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/conversation/chat.d.ts +50 -0
- package/dist/conversation/chat.d.ts.map +1 -0
- package/dist/conversation/chat.js +1145 -0
- package/dist/conversation/chat.js.map +1 -0
- package/dist/conversation/history.d.ts +24 -0
- package/dist/conversation/history.d.ts.map +1 -0
- package/dist/conversation/history.js +103 -0
- package/dist/conversation/history.js.map +1 -0
- package/dist/grok/client.d.ts +86 -0
- package/dist/grok/client.d.ts.map +1 -0
- package/dist/grok/client.js +106 -0
- package/dist/grok/client.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/permissions/manager.d.ts +26 -0
- package/dist/permissions/manager.d.ts.map +1 -0
- package/dist/permissions/manager.js +170 -0
- package/dist/permissions/manager.js.map +1 -0
- package/dist/tools/bash.d.ts +8 -0
- package/dist/tools/bash.d.ts.map +1 -0
- package/dist/tools/bash.js +102 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/edit.d.ts +9 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +61 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/glob.d.ts +7 -0
- package/dist/tools/glob.d.ts.map +1 -0
- package/dist/tools/glob.js +38 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/grep.d.ts +8 -0
- package/dist/tools/grep.d.ts.map +1 -0
- package/dist/tools/grep.js +78 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/read.d.ts +8 -0
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +96 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/registry.d.ts +42 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +230 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/webfetch.d.ts +10 -0
- package/dist/tools/webfetch.d.ts.map +1 -0
- package/dist/tools/webfetch.js +108 -0
- package/dist/tools/webfetch.js.map +1 -0
- package/dist/tools/websearch.d.ts +7 -0
- package/dist/tools/websearch.d.ts.map +1 -0
- package/dist/tools/websearch.js +180 -0
- package/dist/tools/websearch.js.map +1 -0
- package/dist/tools/write.d.ts +7 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +80 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/utils/security.d.ts +36 -0
- package/dist/utils/security.d.ts.map +1 -0
- package/dist/utils/security.js +227 -0
- package/dist/utils/security.js.map +1 -0
- package/dist/utils/ui.d.ts +49 -0
- package/dist/utils/ui.d.ts.map +1 -0
- package/dist/utils/ui.js +302 -0
- package/dist/utils/ui.js.map +1 -0
- package/package.json +45 -0
- package/src/cli.ts +68 -0
- package/src/commands/loader.ts +244 -0
- package/src/config/manager.ts +239 -0
- package/src/conversation/chat.ts +1294 -0
- package/src/conversation/history.ts +131 -0
- package/src/grok/client.ts +192 -0
- package/src/index.ts +8 -0
- package/src/permissions/manager.ts +208 -0
- package/src/tools/bash.ts +119 -0
- package/src/tools/edit.ts +73 -0
- package/src/tools/glob.ts +49 -0
- package/src/tools/grep.ts +96 -0
- package/src/tools/read.ts +116 -0
- package/src/tools/registry.ts +248 -0
- package/src/tools/webfetch.ts +127 -0
- package/src/tools/websearch.ts +219 -0
- package/src/tools/write.ts +94 -0
- package/src/utils/security.ts +259 -0
- package/src/utils/ui.ts +382 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { validatePath } from '../utils/security.js';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
// Maximum file size to write (50MB)
|
|
6
|
+
const MAX_CONTENT_SIZE = 50 * 1024 * 1024;
|
|
7
|
+
export async function writeTool(params) {
|
|
8
|
+
try {
|
|
9
|
+
const filePath = path.resolve(params.file_path);
|
|
10
|
+
// Security validation
|
|
11
|
+
const security = validatePath(filePath);
|
|
12
|
+
if (!security.allowed) {
|
|
13
|
+
return {
|
|
14
|
+
success: false,
|
|
15
|
+
output: '',
|
|
16
|
+
error: `Security: ${security.reason}`,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
// Check content size
|
|
20
|
+
if (params.content.length > MAX_CONTENT_SIZE) {
|
|
21
|
+
return {
|
|
22
|
+
success: false,
|
|
23
|
+
output: '',
|
|
24
|
+
error: `Content too large (${(params.content.length / 1024 / 1024).toFixed(1)}MB). Maximum is ${MAX_CONTENT_SIZE / 1024 / 1024}MB.`,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// Check if file exists (for backup/warning)
|
|
28
|
+
let wasExisting = false;
|
|
29
|
+
let previousSize = 0;
|
|
30
|
+
try {
|
|
31
|
+
const stats = await fs.stat(filePath);
|
|
32
|
+
wasExisting = true;
|
|
33
|
+
previousSize = stats.size;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// File doesn't exist, that's fine
|
|
37
|
+
}
|
|
38
|
+
// Ensure directory exists
|
|
39
|
+
const dir = path.dirname(filePath);
|
|
40
|
+
await fs.mkdir(dir, { recursive: true });
|
|
41
|
+
// Write the file
|
|
42
|
+
await fs.writeFile(filePath, params.content, 'utf-8');
|
|
43
|
+
const lines = params.content.split('\n').length;
|
|
44
|
+
const size = params.content.length;
|
|
45
|
+
let output = `${chalk.green('✓')} File written: ${filePath}\n`;
|
|
46
|
+
output += ` ${chalk.gray('Lines:')} ${lines}\n`;
|
|
47
|
+
output += ` ${chalk.gray('Size:')} ${formatSize(size)}`;
|
|
48
|
+
if (wasExisting) {
|
|
49
|
+
const diff = size - previousSize;
|
|
50
|
+
const diffStr = diff >= 0 ? `+${formatSize(diff)}` : `-${formatSize(Math.abs(diff))}`;
|
|
51
|
+
output += ` (${diffStr} from previous)`;
|
|
52
|
+
}
|
|
53
|
+
// Security warning if applicable
|
|
54
|
+
if (security.severity === 'medium') {
|
|
55
|
+
output = chalk.yellow(`⚠️ ${security.suggestion}\n`) + output;
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
success: true,
|
|
59
|
+
output,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
const err = error;
|
|
64
|
+
if (err.code === 'EACCES') {
|
|
65
|
+
return { success: false, output: '', error: `Permission denied: ${params.file_path}` };
|
|
66
|
+
}
|
|
67
|
+
if (err.code === 'ENOSPC') {
|
|
68
|
+
return { success: false, output: '', error: 'No space left on device' };
|
|
69
|
+
}
|
|
70
|
+
return { success: false, output: '', error: `Error writing file: ${err.message}` };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function formatSize(bytes) {
|
|
74
|
+
if (bytes < 1024)
|
|
75
|
+
return `${bytes}B`;
|
|
76
|
+
if (bytes < 1024 * 1024)
|
|
77
|
+
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
78
|
+
return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides input validation, path traversal prevention, and security checks.
|
|
5
|
+
*/
|
|
6
|
+
export interface SecurityCheckResult {
|
|
7
|
+
allowed: boolean;
|
|
8
|
+
reason?: string;
|
|
9
|
+
severity?: 'low' | 'medium' | 'high' | 'critical';
|
|
10
|
+
suggestion?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Validate a file path for security issues
|
|
14
|
+
*/
|
|
15
|
+
export declare function validatePath(filePath: string, allowedRoots?: string[]): SecurityCheckResult;
|
|
16
|
+
/**
|
|
17
|
+
* Validate a bash command for dangerous patterns
|
|
18
|
+
*/
|
|
19
|
+
export declare function validateCommand(command: string): SecurityCheckResult;
|
|
20
|
+
/**
|
|
21
|
+
* Validate a URL for security issues
|
|
22
|
+
*/
|
|
23
|
+
export declare function validateUrl(url: string): SecurityCheckResult;
|
|
24
|
+
/**
|
|
25
|
+
* Sanitize output for display (prevent terminal escape sequences)
|
|
26
|
+
*/
|
|
27
|
+
export declare function sanitizeOutput(output: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Get safe environment variables (filter out sensitive ones)
|
|
30
|
+
*/
|
|
31
|
+
export declare function getSafeEnv(): Record<string, string>;
|
|
32
|
+
/**
|
|
33
|
+
* Generate a safe temporary path
|
|
34
|
+
*/
|
|
35
|
+
export declare function getSafeTempPath(filename: string): string;
|
|
36
|
+
//# sourceMappingURL=security.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/utils/security.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAsDH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,mBAAmB,CA8C3F;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAiCpE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAiD5D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAkBrD;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgBnD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGxD"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides input validation, path traversal prevention, and security checks.
|
|
5
|
+
*/
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import * as os from 'os';
|
|
8
|
+
// Dangerous patterns that should be flagged
|
|
9
|
+
const DANGEROUS_COMMANDS = [
|
|
10
|
+
/rm\s+-rf\s+[\/~]/i, // rm -rf with root or home
|
|
11
|
+
/rm\s+-rf\s+\*/, // rm -rf *
|
|
12
|
+
/>\s*\/dev\/sd/, // Writing to disk devices
|
|
13
|
+
/mkfs\./, // Formatting filesystems
|
|
14
|
+
/dd\s+if=.*of=\/dev/, // dd to device
|
|
15
|
+
/chmod\s+-R\s+777/, // Recursive 777
|
|
16
|
+
/curl.*\|\s*sh/, // Curl pipe to shell
|
|
17
|
+
/wget.*\|\s*sh/, // Wget pipe to shell
|
|
18
|
+
/curl.*\|\s*bash/,
|
|
19
|
+
/wget.*\|\s*bash/,
|
|
20
|
+
/:(){.*};:/, // Fork bomb pattern
|
|
21
|
+
/>\s*\/etc\//, // Writing to /etc
|
|
22
|
+
/>\s*\/boot\//, // Writing to /boot
|
|
23
|
+
/>\s*\/proc\//, // Writing to /proc
|
|
24
|
+
/>\s*\/sys\//, // Writing to /sys
|
|
25
|
+
];
|
|
26
|
+
// Sensitive file patterns
|
|
27
|
+
const SENSITIVE_FILES = [
|
|
28
|
+
/\.env$/,
|
|
29
|
+
/\.env\./,
|
|
30
|
+
/credentials/i,
|
|
31
|
+
/secret/i,
|
|
32
|
+
/password/i,
|
|
33
|
+
/private_key/,
|
|
34
|
+
/\.pem$/,
|
|
35
|
+
/\.key$/,
|
|
36
|
+
/id_rsa/,
|
|
37
|
+
/id_ed25519/,
|
|
38
|
+
/\.ssh\/config/,
|
|
39
|
+
/\.netrc/,
|
|
40
|
+
/\.npmrc/,
|
|
41
|
+
/\.pypirc/,
|
|
42
|
+
];
|
|
43
|
+
// Blocked paths (never allow access)
|
|
44
|
+
const BLOCKED_PATHS = [
|
|
45
|
+
'/etc/passwd',
|
|
46
|
+
'/etc/shadow',
|
|
47
|
+
'/etc/sudoers',
|
|
48
|
+
'/etc/ssh/',
|
|
49
|
+
'/root/.ssh/',
|
|
50
|
+
'/proc/',
|
|
51
|
+
'/sys/',
|
|
52
|
+
'/dev/',
|
|
53
|
+
];
|
|
54
|
+
/**
|
|
55
|
+
* Validate a file path for security issues
|
|
56
|
+
*/
|
|
57
|
+
export function validatePath(filePath, allowedRoots) {
|
|
58
|
+
// Resolve to absolute path
|
|
59
|
+
const resolved = path.resolve(filePath);
|
|
60
|
+
const normalized = path.normalize(resolved);
|
|
61
|
+
// Check for path traversal attempts
|
|
62
|
+
if (filePath.includes('..')) {
|
|
63
|
+
// Allow if the resolved path is still within allowed roots
|
|
64
|
+
if (allowedRoots && allowedRoots.length > 0) {
|
|
65
|
+
const isWithinRoots = allowedRoots.some(root => normalized.startsWith(path.resolve(root)));
|
|
66
|
+
if (!isWithinRoots) {
|
|
67
|
+
return {
|
|
68
|
+
allowed: false,
|
|
69
|
+
reason: 'Path traversal detected - path escapes allowed directories',
|
|
70
|
+
severity: 'high',
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Check blocked paths
|
|
76
|
+
for (const blocked of BLOCKED_PATHS) {
|
|
77
|
+
if (normalized.startsWith(blocked) || normalized === blocked.slice(0, -1)) {
|
|
78
|
+
return {
|
|
79
|
+
allowed: false,
|
|
80
|
+
reason: `Access to ${blocked} is blocked for security`,
|
|
81
|
+
severity: 'critical',
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Check for sensitive files (warning only)
|
|
86
|
+
for (const pattern of SENSITIVE_FILES) {
|
|
87
|
+
if (pattern.test(normalized)) {
|
|
88
|
+
return {
|
|
89
|
+
allowed: true, // Allow but warn
|
|
90
|
+
reason: 'This appears to be a sensitive file',
|
|
91
|
+
severity: 'medium',
|
|
92
|
+
suggestion: 'Be careful with files containing credentials or secrets',
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return { allowed: true };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Validate a bash command for dangerous patterns
|
|
100
|
+
*/
|
|
101
|
+
export function validateCommand(command) {
|
|
102
|
+
// Check for dangerous patterns
|
|
103
|
+
for (const pattern of DANGEROUS_COMMANDS) {
|
|
104
|
+
if (pattern.test(command)) {
|
|
105
|
+
return {
|
|
106
|
+
allowed: false,
|
|
107
|
+
reason: 'Command matches a dangerous pattern',
|
|
108
|
+
severity: 'critical',
|
|
109
|
+
suggestion: 'This command could cause system damage. Please review carefully.',
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Check for commands that modify critical paths
|
|
114
|
+
if (/>\s*(\/etc|\/boot|\/root|\/var\/log)/i.test(command)) {
|
|
115
|
+
return {
|
|
116
|
+
allowed: false,
|
|
117
|
+
reason: 'Writing to system directories is blocked',
|
|
118
|
+
severity: 'high',
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
// Check for privilege escalation
|
|
122
|
+
if (/sudo\s+-s|su\s+-|sudo\s+su/.test(command)) {
|
|
123
|
+
return {
|
|
124
|
+
allowed: true,
|
|
125
|
+
reason: 'Command requires elevated privileges',
|
|
126
|
+
severity: 'medium',
|
|
127
|
+
suggestion: 'This command will prompt for sudo password',
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return { allowed: true };
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Validate a URL for security issues
|
|
134
|
+
*/
|
|
135
|
+
export function validateUrl(url) {
|
|
136
|
+
try {
|
|
137
|
+
const parsed = new URL(url);
|
|
138
|
+
// Only allow http/https
|
|
139
|
+
if (!['http:', 'https:'].includes(parsed.protocol)) {
|
|
140
|
+
return {
|
|
141
|
+
allowed: false,
|
|
142
|
+
reason: `Protocol ${parsed.protocol} is not allowed`,
|
|
143
|
+
severity: 'medium',
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
// Block localhost/internal IPs (SSRF prevention)
|
|
147
|
+
const hostname = parsed.hostname.toLowerCase();
|
|
148
|
+
const blockedHosts = ['localhost', '127.0.0.1', '0.0.0.0', '::1'];
|
|
149
|
+
const internalPatterns = [
|
|
150
|
+
/^10\./,
|
|
151
|
+
/^172\.(1[6-9]|2[0-9]|3[0-1])\./,
|
|
152
|
+
/^192\.168\./,
|
|
153
|
+
/^169\.254\./,
|
|
154
|
+
];
|
|
155
|
+
if (blockedHosts.includes(hostname)) {
|
|
156
|
+
return {
|
|
157
|
+
allowed: false,
|
|
158
|
+
reason: 'Localhost access is blocked',
|
|
159
|
+
severity: 'high',
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
for (const pattern of internalPatterns) {
|
|
163
|
+
if (pattern.test(hostname)) {
|
|
164
|
+
return {
|
|
165
|
+
allowed: false,
|
|
166
|
+
reason: 'Internal network access is blocked',
|
|
167
|
+
severity: 'high',
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return { allowed: true };
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return {
|
|
175
|
+
allowed: false,
|
|
176
|
+
reason: 'Invalid URL format',
|
|
177
|
+
severity: 'low',
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Sanitize output for display (prevent terminal escape sequences)
|
|
183
|
+
*/
|
|
184
|
+
export function sanitizeOutput(output) {
|
|
185
|
+
// Remove potentially dangerous escape sequences but keep basic formatting
|
|
186
|
+
return output
|
|
187
|
+
// Remove cursor manipulation
|
|
188
|
+
.replace(/\x1b\[\d*[ABCDJK]/g, '')
|
|
189
|
+
// Remove window title changes
|
|
190
|
+
.replace(/\x1b\]0;[^\x07]*\x07/g, '')
|
|
191
|
+
// Remove scrolling region changes
|
|
192
|
+
.replace(/\x1b\[\d*;\d*r/g, '')
|
|
193
|
+
// Keep basic colors (safe)
|
|
194
|
+
.replace(/\x1b\[(\d+;)*\d*[mK]/g, (match) => {
|
|
195
|
+
// Only allow color codes 0-107
|
|
196
|
+
const nums = match.slice(2, -1).split(';').map(Number);
|
|
197
|
+
if (nums.every(n => n >= 0 && n <= 107)) {
|
|
198
|
+
return match;
|
|
199
|
+
}
|
|
200
|
+
return '';
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Get safe environment variables (filter out sensitive ones)
|
|
205
|
+
*/
|
|
206
|
+
export function getSafeEnv() {
|
|
207
|
+
const sensitive = [
|
|
208
|
+
'API_KEY', 'SECRET', 'TOKEN', 'PASSWORD', 'CREDENTIAL',
|
|
209
|
+
'AWS_', 'GITHUB_TOKEN', 'NPM_TOKEN', 'PRIVATE_KEY',
|
|
210
|
+
];
|
|
211
|
+
const result = {};
|
|
212
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
213
|
+
const isSensitive = sensitive.some(s => key.toUpperCase().includes(s));
|
|
214
|
+
if (!isSensitive && value !== undefined) {
|
|
215
|
+
result[key] = value;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Generate a safe temporary path
|
|
222
|
+
*/
|
|
223
|
+
export function getSafeTempPath(filename) {
|
|
224
|
+
const sanitized = filename.replace(/[^a-zA-Z0-9._-]/g, '_');
|
|
225
|
+
return path.join(os.tmpdir(), 'grokcode', sanitized);
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/utils/security.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UI Utilities
|
|
3
|
+
*
|
|
4
|
+
* Beautiful terminal output, syntax highlighting, progress indicators,
|
|
5
|
+
* and user experience enhancements.
|
|
6
|
+
*/
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
export declare const BOX: {
|
|
9
|
+
topLeft: string;
|
|
10
|
+
topRight: string;
|
|
11
|
+
bottomLeft: string;
|
|
12
|
+
bottomRight: string;
|
|
13
|
+
horizontal: string;
|
|
14
|
+
vertical: string;
|
|
15
|
+
teeRight: string;
|
|
16
|
+
teeLeft: string;
|
|
17
|
+
teeDown: string;
|
|
18
|
+
teeUp: string;
|
|
19
|
+
cross: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function drawBox(content: string[], options?: {
|
|
22
|
+
title?: string;
|
|
23
|
+
width?: number;
|
|
24
|
+
padding?: number;
|
|
25
|
+
borderColor?: typeof chalk;
|
|
26
|
+
}): string;
|
|
27
|
+
export declare function highlightCode(code: string, language?: string): string;
|
|
28
|
+
export declare function formatCodeBlock(code: string, language?: string, showLineNumbers?: boolean): string;
|
|
29
|
+
export declare function progressBar(current: number, total: number, width?: number): string;
|
|
30
|
+
export declare function spinner(): {
|
|
31
|
+
start: () => void;
|
|
32
|
+
stop: (success?: boolean) => void;
|
|
33
|
+
update: (text: string) => void;
|
|
34
|
+
};
|
|
35
|
+
export declare function badge(text: string, type?: 'info' | 'success' | 'warning' | 'error'): string;
|
|
36
|
+
export declare function tag(text: string, color?: 'cyan' | 'green' | 'yellow' | 'red' | 'blue' | 'magenta'): string;
|
|
37
|
+
export declare function welcomeScreen(version: string, model: string, cwd: string): string;
|
|
38
|
+
export declare function compactWelcome(version: string, model: string): string;
|
|
39
|
+
export declare function randomTip(): string;
|
|
40
|
+
export declare function table(headers: string[], rows: string[][], options?: {
|
|
41
|
+
padding?: number;
|
|
42
|
+
headerColor?: typeof chalk;
|
|
43
|
+
}): string;
|
|
44
|
+
export declare function formatDiff(oldContent: string, newContent: string): string;
|
|
45
|
+
export declare function truncate(str: string, maxLength: number, suffix?: string): string;
|
|
46
|
+
export declare function indent(text: string, spaces?: number): string;
|
|
47
|
+
export declare function divider(char?: string, length?: number): string;
|
|
48
|
+
export declare function timestamp(): string;
|
|
49
|
+
//# sourceMappingURL=ui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/utils/ui.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,eAAO,MAAM,GAAG;;;;;;;;;;;;CAYf,CAAC;AAEF,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,KAAK,CAAC;CACvB,GAAG,MAAM,CAwDd;AAyBD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CA0BrE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,eAAe,UAAO,GAAG,MAAM,CAgB/F;AAMD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,MAAM,CAO9E;AAED,wBAAgB,OAAO,IAAI;IAAE,KAAK,EAAE,MAAM,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,CAwBlH;AAMD,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAgB,GAAG,MAAM,CAQnG;AAED,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,SAAkB,GAAG,MAAM,CAUlH;AAMD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAoBjF;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAQrE;AAmBD,wBAAgB,SAAS,IAAI,MAAM,CAGlC;AAMD,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,GAAE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,KAAK,CAAC;CACvB,GAAG,MAAM,CA+Bd;AAMD,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CA6BzE;AAUD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,SAAQ,GAAG,MAAM,CAG/E;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,MAAM,CAGvD;AAED,wBAAgB,OAAO,CAAC,IAAI,SAAM,EAAE,MAAM,SAAK,GAAG,MAAM,CAEvD;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC"}
|