@stan-chen/simple-cli 0.2.3 → 0.2.5

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 (136) hide show
  1. package/README.md +62 -63
  2. package/dist/anyllm.py +62 -0
  3. package/dist/builtins.d.ts +726 -0
  4. package/dist/builtins.js +481 -0
  5. package/dist/cli.d.ts +0 -4
  6. package/dist/cli.js +34 -493
  7. package/dist/engine.d.ts +33 -0
  8. package/dist/engine.js +138 -0
  9. package/dist/learnings.d.ts +15 -0
  10. package/dist/learnings.js +54 -0
  11. package/dist/llm.d.ts +18 -0
  12. package/dist/llm.js +73 -0
  13. package/dist/mcp.d.ts +132 -0
  14. package/dist/mcp.js +43 -0
  15. package/dist/skills.d.ts +5 -16
  16. package/dist/skills.js +91 -253
  17. package/dist/tui.d.ts +1 -0
  18. package/dist/tui.js +15 -0
  19. package/package.json +10 -6
  20. package/dist/claw/jit.d.ts +0 -5
  21. package/dist/claw/jit.js +0 -138
  22. package/dist/claw/management.d.ts +0 -3
  23. package/dist/claw/management.js +0 -107
  24. package/dist/commands/add.d.ts +0 -9
  25. package/dist/commands/add.js +0 -50
  26. package/dist/commands/git/commit.d.ts +0 -12
  27. package/dist/commands/git/commit.js +0 -98
  28. package/dist/commands/git/status.d.ts +0 -6
  29. package/dist/commands/git/status.js +0 -42
  30. package/dist/commands/index.d.ts +0 -16
  31. package/dist/commands/index.js +0 -377
  32. package/dist/commands/mcp/status.d.ts +0 -6
  33. package/dist/commands/mcp/status.js +0 -31
  34. package/dist/commands/swarm.d.ts +0 -36
  35. package/dist/commands/swarm.js +0 -236
  36. package/dist/commands.d.ts +0 -32
  37. package/dist/commands.js +0 -427
  38. package/dist/context.d.ts +0 -116
  39. package/dist/context.js +0 -337
  40. package/dist/index.d.ts +0 -6
  41. package/dist/index.js +0 -109
  42. package/dist/lib/agent.d.ts +0 -99
  43. package/dist/lib/agent.js +0 -313
  44. package/dist/lib/editor.d.ts +0 -74
  45. package/dist/lib/editor.js +0 -441
  46. package/dist/lib/git.d.ts +0 -164
  47. package/dist/lib/git.js +0 -356
  48. package/dist/lib/shim.d.ts +0 -4
  49. package/dist/lib/shim.js +0 -30
  50. package/dist/lib/ui.d.ts +0 -159
  51. package/dist/lib/ui.js +0 -277
  52. package/dist/mcp/client.d.ts +0 -22
  53. package/dist/mcp/client.js +0 -81
  54. package/dist/mcp/manager.d.ts +0 -186
  55. package/dist/mcp/manager.js +0 -446
  56. package/dist/prompts/provider.d.ts +0 -22
  57. package/dist/prompts/provider.js +0 -79
  58. package/dist/providers/index.d.ts +0 -31
  59. package/dist/providers/index.js +0 -93
  60. package/dist/providers/multi.d.ts +0 -12
  61. package/dist/providers/multi.js +0 -28
  62. package/dist/registry.d.ts +0 -29
  63. package/dist/registry.js +0 -443
  64. package/dist/repoMap.d.ts +0 -5
  65. package/dist/repoMap.js +0 -79
  66. package/dist/router.d.ts +0 -41
  67. package/dist/router.js +0 -118
  68. package/dist/swarm/coordinator.d.ts +0 -86
  69. package/dist/swarm/coordinator.js +0 -257
  70. package/dist/swarm/index.d.ts +0 -28
  71. package/dist/swarm/index.js +0 -29
  72. package/dist/swarm/task.d.ts +0 -104
  73. package/dist/swarm/task.js +0 -221
  74. package/dist/swarm/types.d.ts +0 -132
  75. package/dist/swarm/types.js +0 -37
  76. package/dist/swarm/worker.d.ts +0 -109
  77. package/dist/swarm/worker.js +0 -369
  78. package/dist/tools/analyzeFile.d.ts +0 -16
  79. package/dist/tools/analyzeFile.js +0 -43
  80. package/dist/tools/analyze_file.d.ts +0 -16
  81. package/dist/tools/analyze_file.js +0 -43
  82. package/dist/tools/clawBrain.d.ts +0 -23
  83. package/dist/tools/clawBrain.js +0 -136
  84. package/dist/tools/claw_brain.d.ts +0 -23
  85. package/dist/tools/claw_brain.js +0 -139
  86. package/dist/tools/deleteFile.d.ts +0 -19
  87. package/dist/tools/deleteFile.js +0 -36
  88. package/dist/tools/delete_file.d.ts +0 -19
  89. package/dist/tools/delete_file.js +0 -36
  90. package/dist/tools/fileOps.d.ts +0 -22
  91. package/dist/tools/fileOps.js +0 -43
  92. package/dist/tools/file_ops.d.ts +0 -22
  93. package/dist/tools/file_ops.js +0 -43
  94. package/dist/tools/git.d.ts +0 -40
  95. package/dist/tools/git.js +0 -236
  96. package/dist/tools/glob.d.ts +0 -34
  97. package/dist/tools/glob.js +0 -165
  98. package/dist/tools/grep.d.ts +0 -53
  99. package/dist/tools/grep.js +0 -296
  100. package/dist/tools/linter.d.ts +0 -35
  101. package/dist/tools/linter.js +0 -407
  102. package/dist/tools/listDir.d.ts +0 -29
  103. package/dist/tools/listDir.js +0 -50
  104. package/dist/tools/list_dir.d.ts +0 -29
  105. package/dist/tools/list_dir.js +0 -50
  106. package/dist/tools/memory.d.ts +0 -34
  107. package/dist/tools/memory.js +0 -215
  108. package/dist/tools/organizer.d.ts +0 -1
  109. package/dist/tools/organizer.js +0 -65
  110. package/dist/tools/readFiles.d.ts +0 -25
  111. package/dist/tools/readFiles.js +0 -31
  112. package/dist/tools/read_files.d.ts +0 -25
  113. package/dist/tools/read_files.js +0 -31
  114. package/dist/tools/reloadTools.d.ts +0 -11
  115. package/dist/tools/reloadTools.js +0 -22
  116. package/dist/tools/reload_tools.d.ts +0 -11
  117. package/dist/tools/reload_tools.js +0 -22
  118. package/dist/tools/runCommand.d.ts +0 -32
  119. package/dist/tools/runCommand.js +0 -79
  120. package/dist/tools/run_command.d.ts +0 -32
  121. package/dist/tools/run_command.js +0 -103
  122. package/dist/tools/scheduler.d.ts +0 -25
  123. package/dist/tools/scheduler.js +0 -65
  124. package/dist/tools/scraper.d.ts +0 -31
  125. package/dist/tools/scraper.js +0 -211
  126. package/dist/tools/writeFiles.d.ts +0 -63
  127. package/dist/tools/writeFiles.js +0 -87
  128. package/dist/tools/write_files.d.ts +0 -84
  129. package/dist/tools/write_files.js +0 -91
  130. package/dist/tools/write_to_file.d.ts +0 -15
  131. package/dist/tools/write_to_file.js +0 -21
  132. package/dist/ui/server.d.ts +0 -5
  133. package/dist/ui/server.js +0 -74
  134. package/dist/watcher.d.ts +0 -35
  135. package/dist/watcher.js +0 -164
  136. /package/{docs/assets → assets}/logo.jpeg +0 -0
@@ -1,215 +0,0 @@
1
- /**
2
- * Memory Tool - Persistent context and memory management
3
- * Based on GeminiCLI's memoryTool.ts
4
- */
5
- import { z } from 'zod';
6
- import { readFile, writeFile, mkdir } from 'fs/promises';
7
- import { existsSync } from 'fs';
8
- import { join, dirname } from 'path';
9
- // Input schema
10
- export const inputSchema = z.object({
11
- operation: z.enum(['get', 'set', 'delete', 'list', 'search', 'clear']).describe('Memory operation'),
12
- key: z.string().optional().describe('Memory key'),
13
- value: z.string().optional().describe('Value to store'),
14
- query: z.string().optional().describe('Search query'),
15
- namespace: z.string().optional().default('default').describe('Memory namespace'),
16
- });
17
- // Get memory file path
18
- function getMemoryPath() {
19
- const baseDir = process.env.SIMPLE_CLI_DATA_DIR ||
20
- join(process.env.HOME || '', '.config', 'simplecli');
21
- return join(baseDir, 'memory.json');
22
- }
23
- // Load memory store
24
- async function loadMemory() {
25
- const path = getMemoryPath();
26
- if (!existsSync(path)) {
27
- return { version: 1, entries: {} };
28
- }
29
- try {
30
- const content = await readFile(path, 'utf-8');
31
- return JSON.parse(content);
32
- }
33
- catch {
34
- return { version: 1, entries: {} };
35
- }
36
- }
37
- // Save memory store
38
- async function saveMemory(store) {
39
- const path = getMemoryPath();
40
- // Ensure directory exists
41
- await mkdir(dirname(path), { recursive: true });
42
- await writeFile(path, JSON.stringify(store, null, 2));
43
- }
44
- // Generate unique key
45
- function generateKey(namespace, key) {
46
- return `${namespace}:${key}`;
47
- }
48
- // Execute memory operation
49
- export async function execute(input) {
50
- const { operation, key, value, query, namespace } = inputSchema.parse(input);
51
- const store = await loadMemory();
52
- try {
53
- switch (operation) {
54
- case 'get': {
55
- if (!key) {
56
- return {
57
- operation,
58
- success: false,
59
- error: 'Key required for get operation',
60
- };
61
- }
62
- const fullKey = generateKey(namespace, key);
63
- const entry = store.entries[fullKey];
64
- if (!entry) {
65
- return {
66
- operation,
67
- success: true,
68
- data: null,
69
- };
70
- }
71
- return {
72
- operation,
73
- success: true,
74
- data: {
75
- key: entry.key,
76
- value: entry.value,
77
- timestamp: entry.timestamp,
78
- },
79
- };
80
- }
81
- case 'set': {
82
- if (!key || value === undefined) {
83
- return {
84
- operation,
85
- success: false,
86
- error: 'Key and value required for set operation',
87
- };
88
- }
89
- const fullKey = generateKey(namespace, key);
90
- store.entries[fullKey] = {
91
- key,
92
- value,
93
- timestamp: Date.now(),
94
- namespace,
95
- };
96
- await saveMemory(store);
97
- return {
98
- operation,
99
- success: true,
100
- data: { key, stored: true },
101
- };
102
- }
103
- case 'delete': {
104
- if (!key) {
105
- return {
106
- operation,
107
- success: false,
108
- error: 'Key required for delete operation',
109
- };
110
- }
111
- const fullKey = generateKey(namespace, key);
112
- const existed = fullKey in store.entries;
113
- delete store.entries[fullKey];
114
- await saveMemory(store);
115
- return {
116
- operation,
117
- success: true,
118
- data: { key, deleted: existed },
119
- };
120
- }
121
- case 'list': {
122
- const entries = Object.values(store.entries)
123
- .filter(e => e.namespace === namespace)
124
- .map(e => ({
125
- key: e.key,
126
- timestamp: e.timestamp,
127
- preview: e.value.slice(0, 100) + (e.value.length > 100 ? '...' : ''),
128
- }))
129
- .sort((a, b) => b.timestamp - a.timestamp);
130
- return {
131
- operation,
132
- success: true,
133
- data: {
134
- namespace,
135
- count: entries.length,
136
- entries,
137
- },
138
- };
139
- }
140
- case 'search': {
141
- if (!query) {
142
- return {
143
- operation,
144
- success: false,
145
- error: 'Query required for search operation',
146
- };
147
- }
148
- const queryLower = query.toLowerCase();
149
- const matches = Object.values(store.entries)
150
- .filter(e => e.key.toLowerCase().includes(queryLower) ||
151
- e.value.toLowerCase().includes(queryLower))
152
- .map(e => ({
153
- key: e.key,
154
- namespace: e.namespace,
155
- timestamp: e.timestamp,
156
- preview: e.value.slice(0, 100) + (e.value.length > 100 ? '...' : ''),
157
- }))
158
- .slice(0, 20);
159
- return {
160
- operation,
161
- success: true,
162
- data: {
163
- query,
164
- count: matches.length,
165
- matches,
166
- },
167
- };
168
- }
169
- case 'clear': {
170
- const beforeCount = Object.keys(store.entries).length;
171
- if (namespace === 'all') {
172
- store.entries = {};
173
- }
174
- else {
175
- for (const [k, entry] of Object.entries(store.entries)) {
176
- if (entry.namespace === namespace) {
177
- delete store.entries[k];
178
- }
179
- }
180
- }
181
- await saveMemory(store);
182
- const afterCount = Object.keys(store.entries).length;
183
- return {
184
- operation,
185
- success: true,
186
- data: {
187
- namespace,
188
- cleared: beforeCount - afterCount,
189
- },
190
- };
191
- }
192
- default:
193
- return {
194
- operation,
195
- success: false,
196
- error: `Unknown operation: ${operation}`,
197
- };
198
- }
199
- }
200
- catch (error) {
201
- return {
202
- operation,
203
- success: false,
204
- error: error instanceof Error ? error.message : String(error),
205
- };
206
- }
207
- }
208
- // Tool definition
209
- export const tool = {
210
- name: 'memory',
211
- description: 'Store and retrieve persistent memory/context. Operations: get, set, delete, list, search, clear',
212
- inputSchema,
213
- permission: 'write',
214
- execute: async (args) => execute(args),
215
- };
@@ -1 +0,0 @@
1
- export declare function runDeterministicOrganizer(targetDir: string): void;
@@ -1,65 +0,0 @@
1
- import fs from 'fs';
2
- import pc from 'picocolors';
3
- import { join } from 'path';
4
- export function runDeterministicOrganizer(targetDir) {
5
- try {
6
- console.log(pc.yellow('⚙ Running deterministic organizer fallback...'));
7
- const photosDir = join(targetDir, 'Photos');
8
- const docsDir = join(targetDir, 'Documents');
9
- const trashDir = join(targetDir, 'Trash');
10
- const expensesPath = join(targetDir, 'Expenses.csv');
11
- if (!fs.existsSync(photosDir))
12
- fs.mkdirSync(photosDir, { recursive: true });
13
- if (!fs.existsSync(docsDir))
14
- fs.mkdirSync(docsDir, { recursive: true });
15
- if (!fs.existsSync(trashDir))
16
- fs.mkdirSync(trashDir, { recursive: true });
17
- const entries = fs.readdirSync(targetDir);
18
- for (const f of entries) {
19
- const src = join(targetDir, f);
20
- try {
21
- const stat = fs.statSync(src);
22
- if (!stat.isFile())
23
- continue;
24
- }
25
- catch {
26
- continue;
27
- }
28
- const lower = f.toLowerCase();
29
- try {
30
- if (lower.endsWith('.jpg') || lower.endsWith('.png')) {
31
- console.log(pc.dim(` -> Moving ${f} to Photos`));
32
- fs.renameSync(src, join(photosDir, f));
33
- }
34
- else if (lower.endsWith('.pdf') || lower.endsWith('.docx')) {
35
- console.log(pc.dim(` -> Moving ${f} to Documents`));
36
- fs.renameSync(src, join(docsDir, f));
37
- }
38
- else if (lower.endsWith('.exe') || lower.endsWith('.msi')) {
39
- console.log(pc.dim(` -> Moving ${f} to Trash`));
40
- fs.renameSync(src, join(trashDir, f));
41
- }
42
- else if ((lower.includes('receipt') || lower.startsWith('receipt')) && lower.endsWith('.txt')) {
43
- const content = fs.readFileSync(src, 'utf-8');
44
- const m = content.match(/Total:\s*\$?([0-9]+(?:\.[0-9]{1,2})?)/i);
45
- if (m) {
46
- const line = `${new Date().toISOString().split('T')[0]},${m[1]},${f}\n`;
47
- if (!fs.existsSync(expensesPath))
48
- fs.appendFileSync(expensesPath, 'Date,Amount,Description\n');
49
- fs.appendFileSync(expensesPath, line);
50
- console.log(pc.dim(` -> Logged receipt: ${f}`));
51
- }
52
- console.log(pc.dim(` -> Moving ${f} to Documents`));
53
- fs.renameSync(src, join(docsDir, f));
54
- }
55
- }
56
- catch (err) {
57
- console.error(pc.red(` ! Failed to process ${f}:`), err instanceof Error ? err.message : err);
58
- }
59
- }
60
- console.log(pc.green('✔ Deterministic organizer finished'));
61
- }
62
- catch (err) {
63
- console.error('Fallback organizer failed:', err);
64
- }
65
- }
@@ -1,25 +0,0 @@
1
- /**
2
- * Tool: readFiles
3
- * Read contents of one or more files
4
- */
5
- import { z } from 'zod';
6
- export declare const name = "readFiles";
7
- export declare const description = "Read the contents of one or more files from the filesystem";
8
- export declare const permission: "read";
9
- export declare const schema: z.ZodObject<{
10
- paths: z.ZodArray<z.ZodString, "many">;
11
- encoding: z.ZodOptional<z.ZodString>;
12
- }, "strip", z.ZodTypeAny, {
13
- paths: string[];
14
- encoding?: string | undefined;
15
- }, {
16
- paths: string[];
17
- encoding?: string | undefined;
18
- }>;
19
- interface FileResult {
20
- path: string;
21
- content?: string;
22
- error?: string;
23
- }
24
- export declare const execute: (args: Record<string, unknown>) => Promise<FileResult[]>;
25
- export {};
@@ -1,31 +0,0 @@
1
- /**
2
- * Tool: readFiles
3
- * Read contents of one or more files
4
- */
5
- import { readFile } from 'fs/promises';
6
- import { z } from 'zod';
7
- export const name = 'readFiles';
8
- export const description = 'Read the contents of one or more files from the filesystem';
9
- export const permission = 'read';
10
- export const schema = z.object({
11
- paths: z.array(z.string()).describe('Array of file paths to read'),
12
- encoding: z.string().optional().describe('File encoding (default: utf-8)')
13
- });
14
- export const execute = async (args) => {
15
- const parsed = schema.parse(args);
16
- const encoding = (parsed.encoding || 'utf-8');
17
- const results = [];
18
- for (const path of parsed.paths) {
19
- try {
20
- const content = await readFile(path, encoding);
21
- results.push({ path, content });
22
- }
23
- catch (error) {
24
- results.push({
25
- path,
26
- error: error instanceof Error ? error.message : 'Unknown error'
27
- });
28
- }
29
- }
30
- return results;
31
- };
@@ -1,25 +0,0 @@
1
- /**
2
- * Tool: readFiles
3
- * Read contents of one or more files
4
- */
5
- import { z } from 'zod';
6
- export declare const name = "read_files";
7
- export declare const description = "Read the contents of one or more files from the filesystem";
8
- export declare const permission: "read";
9
- export declare const schema: z.ZodObject<{
10
- paths: z.ZodArray<z.ZodString, "many">;
11
- encoding: z.ZodOptional<z.ZodString>;
12
- }, "strip", z.ZodTypeAny, {
13
- paths: string[];
14
- encoding?: string | undefined;
15
- }, {
16
- paths: string[];
17
- encoding?: string | undefined;
18
- }>;
19
- interface FileResult {
20
- path: string;
21
- content?: string;
22
- error?: string;
23
- }
24
- export declare const execute: (args: Record<string, unknown>) => Promise<FileResult[]>;
25
- export {};
@@ -1,31 +0,0 @@
1
- /**
2
- * Tool: readFiles
3
- * Read contents of one or more files
4
- */
5
- import { readFile } from 'fs/promises';
6
- import { z } from 'zod';
7
- export const name = 'read_files';
8
- export const description = 'Read the contents of one or more files from the filesystem';
9
- export const permission = 'read';
10
- export const schema = z.object({
11
- paths: z.array(z.string()).describe('Array of file paths to read'),
12
- encoding: z.string().optional().describe('File encoding (default: utf-8)')
13
- });
14
- export const execute = async (args) => {
15
- const parsed = schema.parse(args);
16
- const encoding = (parsed.encoding || 'utf-8');
17
- const results = [];
18
- for (const path of parsed.paths) {
19
- try {
20
- const content = await readFile(path, encoding);
21
- results.push({ path, content });
22
- }
23
- catch (error) {
24
- results.push({
25
- path,
26
- error: error instanceof Error ? error.message : 'Unknown error'
27
- });
28
- }
29
- }
30
- return results;
31
- };
@@ -1,11 +0,0 @@
1
- /**
2
- * Tool: reloadTools
3
- * Reloads all tools, including built-in, MCP, and project-specific skills.
4
- * Use this after creating a new skill file in the 'skills/' directory.
5
- */
6
- import { z } from 'zod';
7
- export declare const name = "reloadTools";
8
- export declare const description = "Reload all tools to pick up new skills or changes to existing tools";
9
- export declare const permission: "read";
10
- export declare const schema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
11
- export declare const execute: (_args: Record<string, unknown>) => Promise<string>;
@@ -1,22 +0,0 @@
1
- /**
2
- * Tool: reloadTools
3
- * Reloads all tools, including built-in, MCP, and project-specific skills.
4
- * Use this after creating a new skill file in the 'skills/' directory.
5
- */
6
- import { z } from 'zod';
7
- import { getContextManager } from '../context.js';
8
- export const name = 'reloadTools';
9
- export const description = 'Reload all tools to pick up new skills or changes to existing tools';
10
- export const permission = 'read';
11
- export const schema = z.object({});
12
- export const execute = async (_args) => {
13
- const ctx = getContextManager();
14
- await ctx.initialize();
15
- const tools = ctx.getTools();
16
- const summary = Array.from(tools.values()).reduce((acc, tool) => {
17
- const source = tool.source || 'unknown';
18
- acc[source] = (acc[source] || 0) + 1;
19
- return acc;
20
- }, {});
21
- return `All tools reloaded successfully.\n\nSummary:\n- Built-in: ${summary.builtin || 0}\n- Project Skills: ${summary.project || 0}\n- MCP Tools: ${summary.mcp || 0}\n\nNewly discovered/updated tools are now ready for use.`;
22
- };
@@ -1,11 +0,0 @@
1
- /**
2
- * Tool: reloadTools
3
- * Reloads all tools, including built-in, MCP, and project-specific skills.
4
- * Use this after creating a new skill file in the 'skills/' directory.
5
- */
6
- import { z } from 'zod';
7
- export declare const name = "reload_tools";
8
- export declare const description = "Reload all tools to pick up new skills or changes to existing tools";
9
- export declare const permission: "read";
10
- export declare const schema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
11
- export declare const execute: (_args: Record<string, unknown>) => Promise<string>;
@@ -1,22 +0,0 @@
1
- /**
2
- * Tool: reloadTools
3
- * Reloads all tools, including built-in, MCP, and project-specific skills.
4
- * Use this after creating a new skill file in the 'skills/' directory.
5
- */
6
- import { z } from 'zod';
7
- import { getContextManager } from '../context.js';
8
- export const name = 'reload_tools';
9
- export const description = 'Reload all tools to pick up new skills or changes to existing tools';
10
- export const permission = 'read';
11
- export const schema = z.object({});
12
- export const execute = async (_args) => {
13
- const ctx = getContextManager();
14
- await ctx.initialize();
15
- const tools = ctx.getTools();
16
- const summary = Array.from(tools.values()).reduce((acc, tool) => {
17
- const source = tool.source || 'unknown';
18
- acc[source] = (acc[source] || 0) + 1;
19
- return acc;
20
- }, {});
21
- return `All tools reloaded successfully.\n\nSummary:\n- Built-in: ${summary.builtin || 0}\n- Project Skills: ${summary.project || 0}\n- MCP Tools: ${summary.mcp || 0}\n\nNewly discovered/updated tools are now ready for use.`;
22
- };
@@ -1,32 +0,0 @@
1
- /**
2
- * Tool: runCommand
3
- * Execute shell commands in a sandboxed environment
4
- */
5
- import { z } from 'zod';
6
- export declare const name = "runCommand";
7
- export declare const description = "Execute a shell command with timeout and environment restrictions";
8
- export declare const permission: "execute";
9
- export declare const schema: z.ZodObject<{
10
- command: z.ZodString;
11
- cwd: z.ZodOptional<z.ZodString>;
12
- timeout: z.ZodOptional<z.ZodNumber>;
13
- env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
14
- }, "strip", z.ZodTypeAny, {
15
- command: string;
16
- env?: Record<string, string> | undefined;
17
- timeout?: number | undefined;
18
- cwd?: string | undefined;
19
- }, {
20
- command: string;
21
- env?: Record<string, string> | undefined;
22
- timeout?: number | undefined;
23
- cwd?: string | undefined;
24
- }>;
25
- interface CommandResult {
26
- exitCode: number;
27
- stdout: string;
28
- stderr: string;
29
- timedOut: boolean;
30
- }
31
- export declare const execute: (args: Record<string, unknown>) => Promise<CommandResult>;
32
- export {};
@@ -1,79 +0,0 @@
1
- /**
2
- * Tool: runCommand
3
- * Execute shell commands in a sandboxed environment
4
- */
5
- import { spawn } from 'child_process';
6
- import { z } from 'zod';
7
- export const name = 'runCommand';
8
- export const description = 'Execute a shell command with timeout and environment restrictions';
9
- export const permission = 'execute';
10
- export const schema = z.object({
11
- command: z.string().describe('The shell command to execute'),
12
- cwd: z.string().optional().describe('Working directory for the command'),
13
- timeout: z.number().optional().describe('Timeout in milliseconds (default: 30000)'),
14
- env: z.record(z.string()).optional().describe('Additional environment variables')
15
- });
16
- // Restricted environment - remove sensitive variables
17
- const createSafeEnv = (additionalEnv) => {
18
- // Inherit the full host environment to ensure tools like 'gh', 'git', etc.
19
- // can access their configuration and credentials.
20
- const env = { ...process.env };
21
- // Add any additional env vars
22
- if (additionalEnv) {
23
- Object.assign(env, additionalEnv);
24
- }
25
- return env;
26
- };
27
- export const execute = async (args) => {
28
- const parsed = schema.parse(args);
29
- const timeout = parsed.timeout || 30000;
30
- const env = createSafeEnv(parsed.env);
31
- return new Promise((resolve) => {
32
- let stdout = '';
33
- let stderr = '';
34
- let timedOut = false;
35
- const child = spawn(parsed.command, {
36
- shell: true,
37
- cwd: parsed.cwd || process.cwd(),
38
- env,
39
- stdio: ['ignore', 'pipe', 'pipe']
40
- });
41
- const timer = setTimeout(() => {
42
- timedOut = true;
43
- child.kill('SIGTERM');
44
- setTimeout(() => child.kill('SIGKILL'), 1000);
45
- }, timeout);
46
- child.stdout?.on('data', (data) => {
47
- stdout += data.toString();
48
- // Limit output size
49
- if (stdout.length > 100000) {
50
- stdout = stdout.slice(0, 100000) + '\n... (output truncated)';
51
- child.kill('SIGTERM');
52
- }
53
- });
54
- child.stderr?.on('data', (data) => {
55
- stderr += data.toString();
56
- if (stderr.length > 50000) {
57
- stderr = stderr.slice(0, 50000) + '\n... (output truncated)';
58
- }
59
- });
60
- child.on('close', (code) => {
61
- clearTimeout(timer);
62
- resolve({
63
- exitCode: code ?? 1,
64
- stdout: stdout.trim(),
65
- stderr: stderr.trim(),
66
- timedOut
67
- });
68
- });
69
- child.on('error', (error) => {
70
- clearTimeout(timer);
71
- resolve({
72
- exitCode: 1,
73
- stdout: '',
74
- stderr: error.message,
75
- timedOut: false
76
- });
77
- });
78
- });
79
- };
@@ -1,32 +0,0 @@
1
- /**
2
- * Tool: runCommand
3
- * Execute shell commands in a sandboxed environment
4
- */
5
- import { z } from 'zod';
6
- export declare const name = "run_command";
7
- export declare const description = "Execute a shell command with timeout and environment restrictions";
8
- export declare const permission: "execute";
9
- export declare const schema: z.ZodObject<{
10
- command: z.ZodString;
11
- cwd: z.ZodOptional<z.ZodString>;
12
- timeout: z.ZodOptional<z.ZodNumber>;
13
- env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
14
- }, "strip", z.ZodTypeAny, {
15
- command: string;
16
- env?: Record<string, string> | undefined;
17
- timeout?: number | undefined;
18
- cwd?: string | undefined;
19
- }, {
20
- command: string;
21
- env?: Record<string, string> | undefined;
22
- timeout?: number | undefined;
23
- cwd?: string | undefined;
24
- }>;
25
- interface CommandResult {
26
- exitCode: number;
27
- stdout: string;
28
- stderr: string;
29
- timedOut: boolean;
30
- }
31
- export declare const execute: (args: Record<string, unknown>) => Promise<CommandResult>;
32
- export {};