@kkeve/suite 0.0.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 (63) hide show
  1. package/dist/agent/factory.d.ts +25 -0
  2. package/dist/agent/factory.js +99 -0
  3. package/dist/agent/index.d.ts +3 -0
  4. package/dist/agent/index.js +7 -0
  5. package/dist/agent/loader.d.ts +22 -0
  6. package/dist/agent/loader.js +117 -0
  7. package/dist/agent/types.d.ts +9 -0
  8. package/dist/agent/types.js +2 -0
  9. package/dist/agent-loop/complete-task.d.ts +28 -0
  10. package/dist/agent-loop/complete-task.js +70 -0
  11. package/dist/agent-loop/index.d.ts +16 -0
  12. package/dist/agent-loop/index.js +26 -0
  13. package/dist/agent-loop/loop.d.ts +42 -0
  14. package/dist/agent-loop/loop.js +282 -0
  15. package/dist/agent-loop/runtime.d.ts +40 -0
  16. package/dist/agent-loop/runtime.js +163 -0
  17. package/dist/agent-loop/types.d.ts +161 -0
  18. package/dist/agent-loop/types.js +105 -0
  19. package/dist/context/index.d.ts +8 -0
  20. package/dist/context/index.js +29 -0
  21. package/dist/context/tokenCalculation.d.ts +55 -0
  22. package/dist/context/tokenCalculation.js +95 -0
  23. package/dist/context/truncation.d.ts +67 -0
  24. package/dist/context/truncation.js +142 -0
  25. package/dist/context/types.d.ts +7 -0
  26. package/dist/context/types.js +27 -0
  27. package/dist/index.d.ts +23 -0
  28. package/dist/index.js +45 -0
  29. package/dist/llm/OpenAIClient.d.ts +31 -0
  30. package/dist/llm/OpenAIClient.js +455 -0
  31. package/dist/llm/constants.d.ts +2 -0
  32. package/dist/llm/constants.js +6 -0
  33. package/dist/llm/errors.d.ts +25 -0
  34. package/dist/llm/errors.js +51 -0
  35. package/dist/llm/index.d.ts +49 -0
  36. package/dist/llm/index.js +158 -0
  37. package/dist/llm/types.d.ts +124 -0
  38. package/dist/llm/types.js +2 -0
  39. package/dist/llm/utils.d.ts +29 -0
  40. package/dist/llm/utils.js +284 -0
  41. package/dist/skill/frontmatter-parser.d.ts +50 -0
  42. package/dist/skill/frontmatter-parser.js +152 -0
  43. package/dist/skill/index.d.ts +12 -0
  44. package/dist/skill/index.js +17 -0
  45. package/dist/skill/loader.d.ts +96 -0
  46. package/dist/skill/loader.js +256 -0
  47. package/dist/tools/ask-user.d.ts +8 -0
  48. package/dist/tools/ask-user.js +47 -0
  49. package/dist/tools/bash.d.ts +47 -0
  50. package/dist/tools/bash.js +213 -0
  51. package/dist/tools/edit-file.d.ts +9 -0
  52. package/dist/tools/edit-file.js +76 -0
  53. package/dist/tools/glob.d.ts +8 -0
  54. package/dist/tools/glob.js +101 -0
  55. package/dist/tools/grep.d.ts +10 -0
  56. package/dist/tools/grep.js +76 -0
  57. package/dist/tools/index.d.ts +24 -0
  58. package/dist/tools/index.js +47 -0
  59. package/dist/tools/read-files.d.ts +8 -0
  60. package/dist/tools/read-files.js +81 -0
  61. package/dist/tools/write-file.d.ts +8 -0
  62. package/dist/tools/write-file.js +63 -0
  63. package/package.json +59 -0
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+ /**
3
+ * Bash Tool — shell command execution with scope-based permission control
4
+ *
5
+ * Scope patterns (aligned with keve-agent SKILL.md allowed-tools):
6
+ * Bash(git:*) → only git commands allowed
7
+ * Bash(npx:*) → only npx commands allowed
8
+ * Bash(npm:*) → only npm commands allowed
9
+ * Bash(node:*) → only node commands allowed
10
+ * Bash(shell:*) → any command allowed
11
+ *
12
+ * When LLM calls bash tool, the 'scope' parameter is validated against
13
+ * the skill's allowed-tools list by the ToolCaller.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.bashTool = exports.BashInputSchema = void 0;
17
+ exports.isCommandInScope = isCommandInScope;
18
+ exports.parseBashScopes = parseBashScopes;
19
+ exports.checkReadOnlyPathWrite = checkReadOnlyPathWrite;
20
+ const v4_1 = require("zod/v4");
21
+ const node_child_process_1 = require("node:child_process");
22
+ // ===== Schema =====
23
+ exports.BashInputSchema = v4_1.z.object({
24
+ /** The shell command to execute */
25
+ command: v4_1.z.string().describe('Shell command to execute'),
26
+ /** Scope constraint (e.g., 'git', 'npx', 'npm', 'node', 'shell') */
27
+ scope: v4_1.z.string().default('shell').describe('Command scope: git/npx/npm/node/shell'),
28
+ /** Working directory */
29
+ cwd: v4_1.z.string().optional().describe('Working directory for command execution'),
30
+ /** Timeout in milliseconds */
31
+ timeout: v4_1.z.number().default(30_000).describe('Execution timeout in ms'),
32
+ });
33
+ // ===== Scope Validation =====
34
+ /**
35
+ * Validate that a command matches the allowed scope.
36
+ * Extracts the first word (the binary name) and checks against scope.
37
+ *
38
+ * @param command - The shell command to validate
39
+ * @param allowedScopes - Array of allowed scopes (e.g., ['git', 'npx', 'shell'])
40
+ * @returns true if command is within allowed scopes
41
+ */
42
+ function isCommandInScope(command, allowedScopes) {
43
+ // 'shell' scope allows everything
44
+ if (allowedScopes.includes('shell'))
45
+ return true;
46
+ // Extract the first word (binary name)
47
+ const firstWord = command.trim().split(/\s+/)[0];
48
+ // Handle path-like commands: extract basename
49
+ const binaryName = firstWord.split('/').pop() ?? firstWord;
50
+ // Check if the binary matches any allowed scope
51
+ return allowedScopes.some(scope => binaryName === scope);
52
+ }
53
+ /**
54
+ * Parse Bash(scope:*) patterns from allowed-tools list.
55
+ * Input: ['Bash(git:*)', 'Bash(npx:*)', 'codegraph_impact']
56
+ * Output: ['git', 'npx']
57
+ */
58
+ function parseBashScopes(allowedTools) {
59
+ const scopes = [];
60
+ for (const tool of allowedTools) {
61
+ const match = tool.match(/^Bash\((\w+):\*\)$/);
62
+ if (match) {
63
+ scopes.push(match[1]);
64
+ }
65
+ }
66
+ return scopes;
67
+ }
68
+ // ===== Read-Only Path Protection =====
69
+ /**
70
+ * Write patterns that indicate a command is trying to modify files.
71
+ * These are checked against readOnlyPaths to prevent writes to protected directories.
72
+ */
73
+ const WRITE_PATTERNS = [
74
+ // sed -i (in-place edit)
75
+ { pattern: /\bsed\s+(-[^-]*i|--in-place)\b/, description: 'sed -i (in-place edit)' },
76
+ // Redirect overwrite: > file (but not >>, > /dev/null, > &)
77
+ { pattern: /[^>]>[^>]/, description: '> redirect (file overwrite)' },
78
+ // Redirect append: >> file (allowed in general, but block if target is readOnly)
79
+ // Actually >> is also a write, let's block it too for readOnly paths
80
+ { pattern: />>/, description: '>> redirect (file append)' },
81
+ // tee command
82
+ { pattern: /\btee\b/, description: 'tee (write to file)' },
83
+ // mv / cp with write target
84
+ { pattern: /\b(mv|cp)\s+/, description: 'mv/cp (move/copy file)' },
85
+ // rm
86
+ { pattern: /\brm\s+/, description: 'rm (delete file)' },
87
+ // chmod / chown
88
+ { pattern: /\b(chmod|chown)\s+/, description: 'chmod/chown (change permissions)' },
89
+ // patch
90
+ { pattern: /\bpatch\s+/, description: 'patch (apply diff)' },
91
+ // npm install / pnpm install / yarn (adds node_modules)
92
+ { pattern: /\b(npm|pnpm|yarn)\s+(install|i|add)\b/, description: 'npm/pnpm/yarn install (add dependencies)' },
93
+ // npx playwright install
94
+ { pattern: /\bnpx\s+playwright\s+install\b/, description: 'npx playwright install (installs browsers)' },
95
+ // pip install
96
+ { pattern: /\bpip\d*\s+install\b/, description: 'pip install (add Python packages)' },
97
+ // echo > redirect
98
+ { pattern: /\becho\s+.*>\s*/, description: 'echo > redirect (write to file)' },
99
+ // cat > redirect
100
+ { pattern: /\bcat\b.*[^>]>[^>]/, description: 'cat > redirect (write to file)' },
101
+ // dd
102
+ { pattern: /\bdd\s+/, description: 'dd (disk write)' },
103
+ // install command (copy files)
104
+ { pattern: /\binstall\s+/, description: 'install (copy files)' },
105
+ ];
106
+ /**
107
+ * Check if a command attempts to write to a read-only path.
108
+ * Uses static analysis of the command string.
109
+ *
110
+ * @param command - The shell command to check
111
+ * @param readOnlyPaths - Array of directory paths that are read-only
112
+ * @returns Error message if write is detected, or null if command is safe
113
+ */
114
+ function checkReadOnlyPathWrite(command, readOnlyPaths) {
115
+ if (!readOnlyPaths.length)
116
+ return null;
117
+ // Step 1: Check if command contains any write pattern
118
+ const matchedPattern = WRITE_PATTERNS.find(p => p.pattern.test(command));
119
+ if (!matchedPattern)
120
+ return null;
121
+ // Step 2: Check if the write target falls under a readOnlyPath
122
+ // Normalize readOnly paths (resolve home, remove trailing slash)
123
+ const normalizedROPaths = readOnlyPaths.map(p => {
124
+ const expanded = p.replace(/^~/, process.env.HOME || '/tmp');
125
+ return expanded.replace(/\/+$/, '');
126
+ });
127
+ // Extract potential target paths from the command
128
+ // Simple heuristic: any absolute path or relative path in the command
129
+ // that starts with or contains a readOnlyPath prefix
130
+ const commandHasReadOnlyTarget = normalizedROPaths.some(roPath => {
131
+ // Direct path reference in command
132
+ if (command.includes(roPath + '/') || command.includes(roPath + ' ') || command.endsWith(roPath)) {
133
+ return true;
134
+ }
135
+ // If cwd might be a readOnlyPath and command uses relative paths
136
+ // (covered by the general pattern match above — if write pattern
137
+ // matches AND readOnlyPath is in the command, we block it)
138
+ return false;
139
+ });
140
+ if (commandHasReadOnlyTarget) {
141
+ return `[BLOCKED] Write operation blocked: "${matchedPattern.description}" targets read-only path. ` +
142
+ `Protected paths: ${normalizedROPaths.join(', ')}. ` +
143
+ `Write your output to workspaceDir instead.`;
144
+ }
145
+ // Even if no explicit path target, some commands are inherently dangerous
146
+ // when executed inside a readOnly directory (e.g., `cd /readOnly && sed -i file`)
147
+ // Check if cwd might be a readOnlyPath
148
+ const cwdInCommand = command.match(/cd\s+(['"]?)(.+?)\1\s+&&/);
149
+ if (cwdInCommand) {
150
+ const cwdPath = cwdInCommand[2].replace(/^~/, process.env.HOME || '/tmp');
151
+ if (normalizedROPaths.some(ro => cwdPath.startsWith(ro))) {
152
+ return `[BLOCKED] Write operation blocked: "${matchedPattern.description}" executed in read-only directory "${cwdPath}". ` +
153
+ `Protected paths: ${normalizedROPaths.join(', ')}. ` +
154
+ `Write your output to workspaceDir instead.`;
155
+ }
156
+ }
157
+ return null;
158
+ }
159
+ // ===== Tool Definition =====
160
+ exports.bashTool = {
161
+ name: 'bash',
162
+ description: `Execute a shell command with scope-based permission control.
163
+
164
+ Scope patterns:
165
+ - Bash(git:*): only git commands
166
+ - Bash(npx:*): only npx commands
167
+ - Bash(npm:*): only npm commands
168
+ - Bash(node:*): only node commands
169
+ - Bash(shell:*): any command
170
+
171
+ The scope parameter is validated against the skill's allowed-tools list.
172
+
173
+ Read-only path protection:
174
+ - If readOnlyPaths is set in context, commands that write to those paths will be blocked.
175
+ - This prevents accidental modification of source code repositories.`,
176
+ inputSchema: exports.BashInputSchema,
177
+ customJsonSchema: {
178
+ type: 'object',
179
+ properties: {
180
+ command: { type: 'string', description: 'Shell command to execute' },
181
+ scope: { type: 'string', description: 'Command scope: git/npx/npm/node/shell', default: 'shell' },
182
+ cwd: { type: 'string', description: 'Working directory' },
183
+ timeout: { type: 'number', description: 'Timeout in ms', default: 30000 },
184
+ },
185
+ required: ['command'],
186
+ },
187
+ async execute(args, context) {
188
+ const { command, scope = 'shell', cwd, timeout = 30_000 } = args;
189
+ // 🆕 Read-only path protection
190
+ if (context?.readOnlyPaths?.length) {
191
+ const blockReason = checkReadOnlyPathWrite(command, context.readOnlyPaths);
192
+ if (blockReason) {
193
+ return { ok: false, stdout: '', stderr: blockReason, exitCode: 126 };
194
+ }
195
+ }
196
+ try {
197
+ const stdout = (0, node_child_process_1.execSync)(command, {
198
+ cwd,
199
+ timeout,
200
+ encoding: 'utf-8',
201
+ maxBuffer: 1024 * 1024, // 1MB
202
+ stdio: ['pipe', 'pipe', 'pipe'],
203
+ });
204
+ return { ok: true, stdout: stdout.trim(), stderr: '', exitCode: 0 };
205
+ }
206
+ catch (err) {
207
+ const stdout = err.stdout?.trim() ?? '';
208
+ const stderr = err.stderr?.trim() ?? '';
209
+ const exitCode = err.status ?? 1;
210
+ return { ok: false, stdout, stderr, exitCode };
211
+ }
212
+ },
213
+ };
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod/v4';
2
+ import type { ToolDefinition } from '../agent-loop/types';
3
+ export declare const EditFileInputSchema: z.ZodObject<{
4
+ path: z.ZodString;
5
+ oldString: z.ZodString;
6
+ newString: z.ZodString;
7
+ replaceAll: z.ZodDefault<z.ZodBoolean>;
8
+ }, z.core.$strip>;
9
+ export declare const editFileTool: ToolDefinition;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.editFileTool = exports.EditFileInputSchema = void 0;
37
+ /**
38
+ * edit_file tool — precise string replacement editing
39
+ *
40
+ * Reference: gemini-cli EditTool (replace oldString → newString)
41
+ */
42
+ const fs = __importStar(require("node:fs/promises"));
43
+ const path = __importStar(require("node:path"));
44
+ const v4_1 = require("zod/v4");
45
+ exports.EditFileInputSchema = v4_1.z.object({
46
+ path: v4_1.z.string().describe('File path'),
47
+ oldString: v4_1.z.string().describe('Original text to replace (must match exactly)'),
48
+ newString: v4_1.z.string().describe('New text to replace with'),
49
+ replaceAll: v4_1.z.boolean().default(false).describe('Replace all occurrences (default: first only)'),
50
+ });
51
+ exports.editFileTool = {
52
+ name: 'edit_file',
53
+ description: 'Edit file by precise string replacement. oldString must match exactly, replaced with newString.',
54
+ inputSchema: exports.EditFileInputSchema,
55
+ execute: async (args, context) => {
56
+ const cwd = context?.cwd ?? process.cwd();
57
+ const filePath = path.isAbsolute(args.path) ? args.path : path.resolve(cwd, args.path);
58
+ const content = await fs.readFile(filePath, 'utf-8');
59
+ // Check if oldString exists
60
+ if (!content.includes(args.oldString)) {
61
+ return { ok: false, error: `oldString not found in ${filePath}` };
62
+ }
63
+ // Check uniqueness (if not replaceAll)
64
+ if (!args.replaceAll) {
65
+ const count = content.split(args.oldString).length - 1;
66
+ if (count > 1) {
67
+ return { ok: false, error: `oldString found ${count} times in ${filePath}, but replaceAll=false. Provide more context to make it unique.` };
68
+ }
69
+ }
70
+ const newContent = args.replaceAll
71
+ ? content.split(args.oldString).join(args.newString)
72
+ : content.replace(args.oldString, args.newString);
73
+ await fs.writeFile(filePath, newContent, 'utf-8');
74
+ return { ok: true, path: filePath, replaced: args.oldString.length };
75
+ },
76
+ };
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod/v4';
2
+ import type { ToolDefinition } from '../agent-loop/types';
3
+ export declare const GlobInputSchema: z.ZodObject<{
4
+ pattern: z.ZodString;
5
+ cwd: z.ZodOptional<z.ZodString>;
6
+ maxResults: z.ZodDefault<z.ZodNumber>;
7
+ }, z.core.$strip>;
8
+ export declare const globTool: ToolDefinition;
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.globTool = exports.GlobInputSchema = void 0;
37
+ /**
38
+ * glob tool — file search with glob pattern matching
39
+ *
40
+ * Reference: gemini-cli GlobTool
41
+ */
42
+ const fs = __importStar(require("node:fs/promises"));
43
+ const path = __importStar(require("node:path"));
44
+ const v4_1 = require("zod/v4");
45
+ exports.GlobInputSchema = v4_1.z.object({
46
+ pattern: v4_1.z.string().describe('Glob pattern (e.g. **/*.vue, src/**/*.ts)'),
47
+ cwd: v4_1.z.string().optional().describe('Root directory to search in'),
48
+ maxResults: v4_1.z.number().default(100).describe('Maximum number of results'),
49
+ });
50
+ exports.globTool = {
51
+ name: 'glob',
52
+ description: 'Search files using glob patterns. Supports **/*.vue, src/**/*.ts etc. Returns matching file paths.',
53
+ inputSchema: exports.GlobInputSchema,
54
+ execute: async (args, context) => {
55
+ const searchDir = args.cwd ?? context?.cwd ?? process.cwd();
56
+ // Simple glob using Node.js fs
57
+ // Production: replace with fast-glob / glob package
58
+ const results = [];
59
+ const pattern = args.pattern;
60
+ async function walk(dir, depth) {
61
+ if (depth > 10 || results.length >= args.maxResults)
62
+ return;
63
+ let entries;
64
+ try {
65
+ entries = await fs.readdir(dir, { withFileTypes: true });
66
+ }
67
+ catch {
68
+ return;
69
+ }
70
+ for (const entry of entries) {
71
+ if (results.length >= args.maxResults)
72
+ break;
73
+ const fullPath = path.join(dir, entry.name);
74
+ // Skip node_modules, .git, dist
75
+ if (entry.isDirectory() && ['node_modules', '.git', 'dist', '.next', '.nuxt'].includes(entry.name))
76
+ continue;
77
+ if (entry.isDirectory()) {
78
+ await walk(fullPath, depth + 1);
79
+ }
80
+ else if (entry.isFile()) {
81
+ const relativePath = path.relative(searchDir, fullPath);
82
+ if (matchGlob(relativePath, pattern)) {
83
+ results.push(relativePath);
84
+ }
85
+ }
86
+ }
87
+ }
88
+ await walk(searchDir, 0);
89
+ return results.sort();
90
+ },
91
+ };
92
+ /** Simple glob matching — supports **, *, ? */
93
+ function matchGlob(filePath, pattern) {
94
+ const regex = pattern
95
+ .replace(/\./g, '\\.')
96
+ .replace(/\*\*/g, '{{GLOBSTAR}}')
97
+ .replace(/\*/g, '[^/]*')
98
+ .replace(/\?/g, '[^/]')
99
+ .replace(/{{GLOBSTAR}}/g, '.*');
100
+ return new RegExp(`^${regex}$`).test(filePath);
101
+ }
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod/v4';
2
+ import type { ToolDefinition } from '../agent-loop/types';
3
+ export declare const GrepInputSchema: z.ZodObject<{
4
+ pattern: z.ZodString;
5
+ path: z.ZodOptional<z.ZodString>;
6
+ include: z.ZodOptional<z.ZodString>;
7
+ maxResults: z.ZodDefault<z.ZodNumber>;
8
+ contextLines: z.ZodDefault<z.ZodNumber>;
9
+ }, z.core.$strip>;
10
+ export declare const grepTool: ToolDefinition;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.grepTool = exports.GrepInputSchema = void 0;
37
+ /**
38
+ * grep tool — content search with regex
39
+ *
40
+ * Reference: gemini-cli GrepTool / ripgrep
41
+ */
42
+ const node_child_process_1 = require("node:child_process");
43
+ const path = __importStar(require("node:path"));
44
+ const v4_1 = require("zod/v4");
45
+ exports.GrepInputSchema = v4_1.z.object({
46
+ pattern: v4_1.z.string().describe('Regex pattern to search for'),
47
+ path: v4_1.z.string().optional().describe('Directory to search in'),
48
+ include: v4_1.z.string().optional().describe('File filter pattern (e.g. *.vue, *.ts)'),
49
+ maxResults: v4_1.z.number().default(50).describe('Maximum number of matches to return'),
50
+ contextLines: v4_1.z.number().default(2).describe('Number of context lines around matches'),
51
+ });
52
+ exports.grepTool = {
53
+ name: 'grep',
54
+ description: 'Search file contents with regex. Returns matching file paths, line numbers, and content.',
55
+ inputSchema: exports.GrepInputSchema,
56
+ execute: async (args, context) => {
57
+ const searchDir = args.path ?? context?.cwd ?? process.cwd();
58
+ const absPath = path.isAbsolute(searchDir) ? searchDir : path.resolve(context?.cwd ?? process.cwd(), searchDir);
59
+ const includeFlag = args.include ? `--include="${args.include}"` : '';
60
+ const contextFlag = args.contextLines > 0 ? `-C ${args.contextLines}` : '';
61
+ const maxCount = args.maxResults > 0 ? `-m ${args.maxResults}` : '';
62
+ try {
63
+ const result = (0, node_child_process_1.execSync)(`grep -rn ${contextFlag} ${maxCount} ${includeFlag} -E "${args.pattern.replace(/"/g, '\\"')}" "${absPath}" 2>/dev/null || true`, { encoding: 'utf-8', timeout: 15_000, maxBuffer: 1024 * 1024 }).trim();
64
+ if (!result)
65
+ return { matches: [], count: 0 };
66
+ const lines = result.split('\n').filter(Boolean);
67
+ return {
68
+ matches: lines.slice(0, args.maxResults),
69
+ count: lines.length,
70
+ };
71
+ }
72
+ catch {
73
+ return { matches: [], count: 0 };
74
+ }
75
+ },
76
+ };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Tool registry factory — general tools
3
+ *
4
+ * General tools (gemini-cli aligned):
5
+ * - bash, read_files, write_file, edit_file, glob, grep, ask_user
6
+ *
7
+ * Business tools (keve, record_step_result) have been moved to agent package.
8
+ * MCP browser tools (pw_*) have been removed — use keve-suite or agent package instead.
9
+ */
10
+ import { ToolRegistry } from '../agent-loop/types';
11
+ import type { RuntimeEnvironment } from '../agent-loop/runtime';
12
+ import { bashTool } from './bash';
13
+ import { readFilesTool } from './read-files';
14
+ import { writeFileTool } from './write-file';
15
+ import { editFileTool } from './edit-file';
16
+ import { globTool } from './glob';
17
+ import { grepTool } from './grep';
18
+ import { askUserTool } from './ask-user';
19
+ export { bashTool, readFilesTool, writeFileTool, editFileTool, globTool, grepTool, askUserTool };
20
+ /**
21
+ * Create default tool registry — general tools only
22
+ */
23
+ export declare function createDefaultToolRegistry(runtime: RuntimeEnvironment): ToolRegistry;
24
+ export declare function getBuiltinToolNames(): string[];
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ /**
3
+ * Tool registry factory — general tools
4
+ *
5
+ * General tools (gemini-cli aligned):
6
+ * - bash, read_files, write_file, edit_file, glob, grep, ask_user
7
+ *
8
+ * Business tools (keve, record_step_result) have been moved to agent package.
9
+ * MCP browser tools (pw_*) have been removed — use keve-suite or agent package instead.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.askUserTool = exports.grepTool = exports.globTool = exports.editFileTool = exports.writeFileTool = exports.readFilesTool = exports.bashTool = void 0;
13
+ exports.createDefaultToolRegistry = createDefaultToolRegistry;
14
+ exports.getBuiltinToolNames = getBuiltinToolNames;
15
+ const types_1 = require("../agent-loop/types");
16
+ const bash_1 = require("./bash");
17
+ Object.defineProperty(exports, "bashTool", { enumerable: true, get: function () { return bash_1.bashTool; } });
18
+ const read_files_1 = require("./read-files");
19
+ Object.defineProperty(exports, "readFilesTool", { enumerable: true, get: function () { return read_files_1.readFilesTool; } });
20
+ const write_file_1 = require("./write-file");
21
+ Object.defineProperty(exports, "writeFileTool", { enumerable: true, get: function () { return write_file_1.writeFileTool; } });
22
+ const edit_file_1 = require("./edit-file");
23
+ Object.defineProperty(exports, "editFileTool", { enumerable: true, get: function () { return edit_file_1.editFileTool; } });
24
+ const glob_1 = require("./glob");
25
+ Object.defineProperty(exports, "globTool", { enumerable: true, get: function () { return glob_1.globTool; } });
26
+ const grep_1 = require("./grep");
27
+ Object.defineProperty(exports, "grepTool", { enumerable: true, get: function () { return grep_1.grepTool; } });
28
+ const ask_user_1 = require("./ask-user");
29
+ Object.defineProperty(exports, "askUserTool", { enumerable: true, get: function () { return ask_user_1.askUserTool; } });
30
+ /**
31
+ * Create default tool registry — general tools only
32
+ */
33
+ function createDefaultToolRegistry(runtime) {
34
+ globalThis.__runtime = runtime;
35
+ const registry = new types_1.ToolRegistry();
36
+ registry.register(bash_1.bashTool);
37
+ registry.register(read_files_1.readFilesTool);
38
+ registry.register(write_file_1.writeFileTool);
39
+ registry.register(edit_file_1.editFileTool);
40
+ registry.register(glob_1.globTool);
41
+ registry.register(grep_1.grepTool);
42
+ registry.register(ask_user_1.askUserTool);
43
+ return registry;
44
+ }
45
+ function getBuiltinToolNames() {
46
+ return ['bash', 'read_files', 'write_file', 'edit_file', 'glob', 'grep', 'ask_user'];
47
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * read_files Tool — multi-file reader (reference: gemini-cli ReadManyFilesTool)
3
+ *
4
+ * Reads multiple files at once, with content truncation.
5
+ * Used by skills to read code, configs, wiki content, etc.
6
+ */
7
+ import type { ToolDefinition } from '../agent-loop/types';
8
+ export declare const readFilesTool: ToolDefinition;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ /**
3
+ * read_files Tool — multi-file reader (reference: gemini-cli ReadManyFilesTool)
4
+ *
5
+ * Reads multiple files at once, with content truncation.
6
+ * Used by skills to read code, configs, wiki content, etc.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.readFilesTool = void 0;
43
+ const v4_1 = require("zod/v4");
44
+ const fs = __importStar(require("node:fs/promises"));
45
+ const path = __importStar(require("node:path"));
46
+ const ReadFilesSchema = v4_1.z.object({
47
+ /** File paths to read (absolute or relative to cwd) */
48
+ paths: v4_1.z.array(v4_1.z.string()).describe('Array of file paths to read'),
49
+ /** Base directory for resolving relative paths */
50
+ cwd: v4_1.z.string().optional().describe('Base directory for relative paths'),
51
+ /** Max bytes per file (prevents OOM on large files) */
52
+ maxBytes: v4_1.z.number().default(50_000).describe('Max bytes per file (truncated if larger)'),
53
+ });
54
+ exports.readFilesTool = {
55
+ name: 'read_files',
56
+ description: `Read multiple files at once. Returns file contents with path headers.
57
+ Files larger than maxBytes are truncated. Non-existent files produce an error message.`,
58
+ inputSchema: ReadFilesSchema,
59
+ async execute(args) {
60
+ const { paths, cwd, maxBytes = 50_000 } = args;
61
+ const baseDir = cwd ?? process.cwd();
62
+ const results = [];
63
+ for (const filePath of paths) {
64
+ const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(baseDir, filePath);
65
+ const header = `\n=== ${filePath} ===`;
66
+ try {
67
+ const content = await fs.readFile(absPath, 'utf-8');
68
+ if (content.length > maxBytes) {
69
+ results.push(`${header}\n${content.slice(0, maxBytes)}\n... [truncated at ${maxBytes} chars]`);
70
+ }
71
+ else {
72
+ results.push(`${header}\n${content}`);
73
+ }
74
+ }
75
+ catch (err) {
76
+ results.push(`${header}\n[Error: ${err.message}]`);
77
+ }
78
+ }
79
+ return results.join('\n');
80
+ },
81
+ };
@@ -0,0 +1,8 @@
1
+ import { z } from 'zod/v4';
2
+ import type { ToolDefinition } from '../agent-loop/types';
3
+ export declare const WriteFileInputSchema: z.ZodObject<{
4
+ path: z.ZodString;
5
+ content: z.ZodString;
6
+ createDirs: z.ZodDefault<z.ZodBoolean>;
7
+ }, z.core.$strip>;
8
+ export declare const writeFileTool: ToolDefinition;