llm-agent-cli 2.0.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 (89) hide show
  1. package/dist/agent.d.ts +112 -0
  2. package/dist/agent.d.ts.map +1 -0
  3. package/dist/agent.js +730 -0
  4. package/dist/agent.js.map +1 -0
  5. package/dist/audit.d.ts +24 -0
  6. package/dist/audit.d.ts.map +1 -0
  7. package/dist/audit.js +94 -0
  8. package/dist/audit.js.map +1 -0
  9. package/dist/auth.d.ts +36 -0
  10. package/dist/auth.d.ts.map +1 -0
  11. package/dist/auth.js +236 -0
  12. package/dist/auth.js.map +1 -0
  13. package/dist/config.d.ts +35 -0
  14. package/dist/config.d.ts.map +1 -0
  15. package/dist/config.js +92 -0
  16. package/dist/config.js.map +1 -0
  17. package/dist/context.d.ts +48 -0
  18. package/dist/context.d.ts.map +1 -0
  19. package/dist/context.js +94 -0
  20. package/dist/context.js.map +1 -0
  21. package/dist/diff.d.ts +27 -0
  22. package/dist/diff.d.ts.map +1 -0
  23. package/dist/diff.js +174 -0
  24. package/dist/diff.js.map +1 -0
  25. package/dist/index.d.ts +3 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +905 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/input.d.ts +13 -0
  30. package/dist/input.d.ts.map +1 -0
  31. package/dist/input.js +88 -0
  32. package/dist/input.js.map +1 -0
  33. package/dist/memory.d.ts +32 -0
  34. package/dist/memory.d.ts.map +1 -0
  35. package/dist/memory.js +103 -0
  36. package/dist/memory.js.map +1 -0
  37. package/dist/preprocessor.d.ts +12 -0
  38. package/dist/preprocessor.d.ts.map +1 -0
  39. package/dist/preprocessor.js +138 -0
  40. package/dist/preprocessor.js.map +1 -0
  41. package/dist/project.d.ts +10 -0
  42. package/dist/project.d.ts.map +1 -0
  43. package/dist/project.js +145 -0
  44. package/dist/project.js.map +1 -0
  45. package/dist/renderer.d.ts +2 -0
  46. package/dist/renderer.d.ts.map +1 -0
  47. package/dist/renderer.js +31 -0
  48. package/dist/renderer.js.map +1 -0
  49. package/dist/session.d.ts +36 -0
  50. package/dist/session.d.ts.map +1 -0
  51. package/dist/session.js +78 -0
  52. package/dist/session.js.map +1 -0
  53. package/dist/tools/filesystem.d.ts +138 -0
  54. package/dist/tools/filesystem.d.ts.map +1 -0
  55. package/dist/tools/filesystem.js +539 -0
  56. package/dist/tools/filesystem.js.map +1 -0
  57. package/dist/tools/git.d.ts +60 -0
  58. package/dist/tools/git.d.ts.map +1 -0
  59. package/dist/tools/git.js +188 -0
  60. package/dist/tools/git.js.map +1 -0
  61. package/dist/tools/index.d.ts +386 -0
  62. package/dist/tools/index.d.ts.map +1 -0
  63. package/dist/tools/index.js +142 -0
  64. package/dist/tools/index.js.map +1 -0
  65. package/dist/tools/linter.d.ts +44 -0
  66. package/dist/tools/linter.d.ts.map +1 -0
  67. package/dist/tools/linter.js +426 -0
  68. package/dist/tools/linter.js.map +1 -0
  69. package/dist/tools/network.d.ts +17 -0
  70. package/dist/tools/network.d.ts.map +1 -0
  71. package/dist/tools/network.js +121 -0
  72. package/dist/tools/network.js.map +1 -0
  73. package/dist/tools/search.d.ts +33 -0
  74. package/dist/tools/search.d.ts.map +1 -0
  75. package/dist/tools/search.js +263 -0
  76. package/dist/tools/search.js.map +1 -0
  77. package/dist/tools/security.d.ts +18 -0
  78. package/dist/tools/security.d.ts.map +1 -0
  79. package/dist/tools/security.js +242 -0
  80. package/dist/tools/security.js.map +1 -0
  81. package/dist/tools/shell.d.ts +14 -0
  82. package/dist/tools/shell.d.ts.map +1 -0
  83. package/dist/tools/shell.js +68 -0
  84. package/dist/tools/shell.js.map +1 -0
  85. package/dist/tools/types.d.ts +5 -0
  86. package/dist/tools/types.d.ts.map +1 -0
  87. package/dist/tools/types.js +2 -0
  88. package/dist/tools/types.js.map +1 -0
  89. package/package.json +59 -0
@@ -0,0 +1,242 @@
1
+ import fs from "fs/promises";
2
+ import ignore from "ignore";
3
+ import os from "os";
4
+ import path from "path";
5
+ import { confirm } from "@inquirer/prompts";
6
+ const DEFAULT_CONFIG = {
7
+ workspaceRoot: path.resolve(process.cwd()),
8
+ permissionMode: "standard",
9
+ maxReadBytes: 100 * 1024,
10
+ maxToolResultChars: 50_000,
11
+ maxCommandOutputChars: 50_000,
12
+ shellTimeoutMs: 30_000,
13
+ };
14
+ let runtimeConfig = { ...DEFAULT_CONFIG };
15
+ let workspaceRealPathCache = null;
16
+ let ignoreMatcherCache = null;
17
+ let ignorePathCache = null;
18
+ let ignoreMtimeCache = null;
19
+ const BLACKLIST_PATTERNS = [
20
+ {
21
+ regex: /(^|\s)rm\s+-rf\s+\/(\s|$)/i,
22
+ reason: "Blocked dangerous command pattern: rm -rf /",
23
+ },
24
+ {
25
+ regex: /:\(\)\s*\{\s*:\|:\s*&\s*\};:/,
26
+ reason: "Blocked dangerous command pattern: fork bomb",
27
+ },
28
+ {
29
+ regex: /(^|\s)dd\s+if=/i,
30
+ reason: "Blocked dangerous command pattern: dd if=",
31
+ },
32
+ {
33
+ regex: /(^|\s)mkfs(\.|\s|$)/i,
34
+ reason: "Blocked dangerous command pattern: mkfs",
35
+ },
36
+ {
37
+ regex: /curl\b[^\n\r|]*\|\s*(bash|sh)\b/i,
38
+ reason: "Blocked dangerous command pattern: curl | bash",
39
+ },
40
+ {
41
+ regex: /wget\b[^\n\r|]*\|\s*(bash|sh)\b/i,
42
+ reason: "Blocked dangerous command pattern: wget | bash",
43
+ },
44
+ ];
45
+ function parseEnvNumber(value, fallback) {
46
+ if (!value)
47
+ return fallback;
48
+ const parsed = Number.parseInt(value, 10);
49
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
50
+ }
51
+ function expandHome(inputPath) {
52
+ if (inputPath === "~")
53
+ return os.homedir();
54
+ if (inputPath.startsWith("~/"))
55
+ return path.join(os.homedir(), inputPath.slice(2));
56
+ return inputPath;
57
+ }
58
+ function toPosix(relativePath) {
59
+ return relativePath.split(path.sep).join("/");
60
+ }
61
+ async function pathExists(absPath) {
62
+ try {
63
+ await fs.access(absPath);
64
+ return true;
65
+ }
66
+ catch {
67
+ return false;
68
+ }
69
+ }
70
+ async function getWorkspaceRealPath() {
71
+ if (workspaceRealPathCache)
72
+ return workspaceRealPathCache;
73
+ try {
74
+ workspaceRealPathCache = await fs.realpath(runtimeConfig.workspaceRoot);
75
+ }
76
+ catch {
77
+ workspaceRealPathCache = path.resolve(runtimeConfig.workspaceRoot);
78
+ }
79
+ return workspaceRealPathCache;
80
+ }
81
+ async function resolveExistingAncestor(absPath) {
82
+ let current = absPath;
83
+ while (true) {
84
+ if (await pathExists(current)) {
85
+ try {
86
+ return await fs.realpath(current);
87
+ }
88
+ catch {
89
+ return path.resolve(current);
90
+ }
91
+ }
92
+ const parent = path.dirname(current);
93
+ if (parent === current) {
94
+ return path.resolve(absPath);
95
+ }
96
+ current = parent;
97
+ }
98
+ }
99
+ async function loadIgnoreMatcher() {
100
+ const ignorePath = path.join(runtimeConfig.workspaceRoot, ".agentignore");
101
+ // Hot-reload: stat the file to get current mtime.
102
+ // If mtime has changed (or the file appeared/disappeared), bust the cache.
103
+ let currentMtime = null;
104
+ try {
105
+ const stat = await fs.stat(ignorePath);
106
+ currentMtime = stat.mtimeMs;
107
+ }
108
+ catch {
109
+ // File does not exist — currentMtime stays null.
110
+ }
111
+ if (ignorePath === ignorePathCache &&
112
+ ignoreMatcherCache !== null &&
113
+ currentMtime === ignoreMtimeCache) {
114
+ return ignoreMatcherCache;
115
+ }
116
+ ignorePathCache = ignorePath;
117
+ ignoreMtimeCache = currentMtime;
118
+ const matcher = ignore();
119
+ if (currentMtime !== null) {
120
+ try {
121
+ const raw = await fs.readFile(ignorePath, "utf-8");
122
+ matcher.add(raw);
123
+ }
124
+ catch {
125
+ // File disappeared between stat and read — use empty matcher.
126
+ }
127
+ }
128
+ ignoreMatcherCache = matcher;
129
+ return matcher;
130
+ }
131
+ async function isIgnoredByRules(relativePath) {
132
+ const matcher = await loadIgnoreMatcher();
133
+ return matcher.ignores(relativePath);
134
+ }
135
+ async function assertWithinWorkspace(absPath) {
136
+ const workspaceRealPath = await getWorkspaceRealPath();
137
+ const candidateRealPath = await resolveExistingAncestor(absPath);
138
+ const relative = path.relative(workspaceRealPath, candidateRealPath);
139
+ const outside = relative.startsWith("..") ||
140
+ path.isAbsolute(relative);
141
+ if (outside) {
142
+ throw new Error(`Path is outside workspace root (${runtimeConfig.workspaceRoot}): ${absPath}`);
143
+ }
144
+ }
145
+ export async function resolveProtectedPath(inputPath) {
146
+ const expanded = expandHome(inputPath);
147
+ const absPath = path.resolve(path.isAbsolute(expanded) ? expanded : path.resolve(process.cwd(), expanded));
148
+ await assertWithinWorkspace(absPath);
149
+ const relative = toPosix(path.relative(runtimeConfig.workspaceRoot, absPath));
150
+ if (relative.startsWith("..") || path.isAbsolute(relative)) {
151
+ throw new Error(`Path is outside workspace root (${runtimeConfig.workspaceRoot}): ${absPath}`);
152
+ }
153
+ if (relative && (await isIgnoredByRules(relative))) {
154
+ throw new Error(`Path is blocked by .agentignore: ${absPath}`);
155
+ }
156
+ return absPath;
157
+ }
158
+ export function getRuntimeConfig() {
159
+ return { ...runtimeConfig };
160
+ }
161
+ export function setRuntimeConfig(nextConfig) {
162
+ const currentRoot = runtimeConfig.workspaceRoot;
163
+ const incomingRoot = nextConfig.workspaceRoot
164
+ ? path.resolve(expandHome(nextConfig.workspaceRoot))
165
+ : currentRoot;
166
+ runtimeConfig = {
167
+ workspaceRoot: incomingRoot,
168
+ permissionMode: nextConfig.permissionMode ?? runtimeConfig.permissionMode,
169
+ maxReadBytes: nextConfig.maxReadBytes ?? runtimeConfig.maxReadBytes,
170
+ maxToolResultChars: nextConfig.maxToolResultChars ?? runtimeConfig.maxToolResultChars,
171
+ maxCommandOutputChars: nextConfig.maxCommandOutputChars ?? runtimeConfig.maxCommandOutputChars,
172
+ shellTimeoutMs: nextConfig.shellTimeoutMs ?? runtimeConfig.shellTimeoutMs,
173
+ };
174
+ if (incomingRoot !== currentRoot) {
175
+ workspaceRealPathCache = null;
176
+ ignoreMatcherCache = null;
177
+ ignorePathCache = null;
178
+ }
179
+ }
180
+ export function initializeRuntimeFromEnv() {
181
+ setRuntimeConfig({
182
+ workspaceRoot: process.env.LLM_AGENT_WORKSPACE_ROOT || DEFAULT_CONFIG.workspaceRoot,
183
+ permissionMode: process.env.LLM_AGENT_PERMISSION_MODE ??
184
+ DEFAULT_CONFIG.permissionMode,
185
+ maxReadBytes: parseEnvNumber(process.env.LLM_AGENT_MAX_READ_BYTES, DEFAULT_CONFIG.maxReadBytes),
186
+ maxToolResultChars: parseEnvNumber(process.env.LLM_AGENT_MAX_TOOL_RESULT_CHARS, DEFAULT_CONFIG.maxToolResultChars),
187
+ maxCommandOutputChars: parseEnvNumber(process.env.LLM_AGENT_MAX_COMMAND_OUTPUT_CHARS, DEFAULT_CONFIG.maxCommandOutputChars),
188
+ shellTimeoutMs: parseEnvNumber(process.env.LLM_AGENT_SHELL_TIMEOUT_MS, DEFAULT_CONFIG.shellTimeoutMs),
189
+ });
190
+ }
191
+ export function getBlockedCommandReason(command) {
192
+ for (const entry of BLACKLIST_PATTERNS) {
193
+ if (entry.regex.test(command)) {
194
+ return entry.reason;
195
+ }
196
+ }
197
+ return null;
198
+ }
199
+ async function requireUserConfirmation(message) {
200
+ if (runtimeConfig.permissionMode === "yolo")
201
+ return;
202
+ if (!process.stdin.isTTY) {
203
+ throw new Error(`Operation requires confirmation in ${runtimeConfig.permissionMode} mode, but no TTY is available.`);
204
+ }
205
+ const approved = await confirm({
206
+ message,
207
+ default: false,
208
+ });
209
+ if (!approved) {
210
+ throw new Error("User denied operation.");
211
+ }
212
+ }
213
+ export async function enforceWritePolicy(actionDescription) {
214
+ if (runtimeConfig.permissionMode === "safe") {
215
+ throw new Error(`Write operations are disabled in safe mode: ${actionDescription}`);
216
+ }
217
+ if (runtimeConfig.permissionMode === "standard") {
218
+ await requireUserConfirmation(`Allow: ${actionDescription}?`);
219
+ }
220
+ }
221
+ export async function enforceCommandPolicy(command) {
222
+ const blockedReason = getBlockedCommandReason(command);
223
+ if (blockedReason) {
224
+ throw new Error(blockedReason);
225
+ }
226
+ if (runtimeConfig.permissionMode === "safe") {
227
+ throw new Error("Shell commands are disabled in safe mode.");
228
+ }
229
+ if (runtimeConfig.permissionMode === "standard") {
230
+ await requireUserConfirmation(`Allow running this command? ${command}`);
231
+ }
232
+ }
233
+ export async function isPathIgnored(absPath) {
234
+ const normalized = path.resolve(absPath);
235
+ const relative = toPosix(path.relative(runtimeConfig.workspaceRoot, normalized));
236
+ if (!relative || relative.startsWith("..") || path.isAbsolute(relative)) {
237
+ return true;
238
+ }
239
+ return isIgnoredByRules(relative);
240
+ }
241
+ initializeRuntimeFromEnv();
242
+ //# sourceMappingURL=security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/tools/security.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { z } from "zod";
2
+ import type { ToolExecutionContext } from "./types.js";
3
+ export declare const RunBashCommandSchema: z.ZodObject<{
4
+ command: z.ZodString;
5
+ timeout_ms: z.ZodOptional<z.ZodNumber>;
6
+ }, "strip", z.ZodTypeAny, {
7
+ command: string;
8
+ timeout_ms?: number | undefined;
9
+ }, {
10
+ command: string;
11
+ timeout_ms?: number | undefined;
12
+ }>;
13
+ export declare function run_bash_command(args: z.infer<typeof RunBashCommandSchema>, context: ToolExecutionContext): Promise<string>;
14
+ //# sourceMappingURL=shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/tools/shell.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAIvD,eAAO,MAAM,oBAAoB;;;;;;;;;EAS/B,CAAC;AAgCH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,EAC1C,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAqCjB"}
@@ -0,0 +1,68 @@
1
+ import { exec } from "child_process";
2
+ import { promisify } from "util";
3
+ import { z } from "zod";
4
+ import { enforceCommandPolicy, getRuntimeConfig, } from "./security.js";
5
+ const execAsync = promisify(exec);
6
+ export const RunBashCommandSchema = z.object({
7
+ command: z.string().min(1).describe("Shell command to execute"),
8
+ timeout_ms: z
9
+ .number()
10
+ .int()
11
+ .positive()
12
+ .max(120000)
13
+ .optional()
14
+ .describe("Optional timeout override in milliseconds"),
15
+ });
16
+ function formatOutput(stdout, stderr) {
17
+ const parts = [];
18
+ if (stdout.trim()) {
19
+ parts.push(`stdout:\n${stdout.trim()}`);
20
+ }
21
+ if (stderr.trim()) {
22
+ parts.push(`stderr:\n${stderr.trim()}`);
23
+ }
24
+ if (parts.length === 0) {
25
+ return "(command produced no output)";
26
+ }
27
+ return parts.join("\n\n");
28
+ }
29
+ function truncateOutput(output) {
30
+ const { maxCommandOutputChars } = getRuntimeConfig();
31
+ if (output.length <= maxCommandOutputChars) {
32
+ return output;
33
+ }
34
+ const remaining = output.length - maxCommandOutputChars;
35
+ return [
36
+ output.slice(0, maxCommandOutputChars),
37
+ "",
38
+ `[Output truncated: removed ${remaining} characters due to MAX_COMMAND_OUTPUT_CHARS=${maxCommandOutputChars}]`,
39
+ ].join("\n");
40
+ }
41
+ export async function run_bash_command(args, context) {
42
+ const parsed = RunBashCommandSchema.parse(args);
43
+ try {
44
+ await enforceCommandPolicy(parsed.command);
45
+ const runtime = getRuntimeConfig();
46
+ const timeout = parsed.timeout_ms ?? runtime.shellTimeoutMs;
47
+ const result = await execAsync(parsed.command, {
48
+ cwd: process.cwd(),
49
+ timeout,
50
+ signal: context.abortSignal,
51
+ maxBuffer: 8 * 1024 * 1024,
52
+ });
53
+ return truncateOutput(formatOutput(result.stdout, result.stderr));
54
+ }
55
+ catch (err) {
56
+ if (err && typeof err === "object") {
57
+ const maybeAny = err;
58
+ const stdout = maybeAny.stdout ?? "";
59
+ const stderr = maybeAny.stderr ?? "";
60
+ const body = formatOutput(stdout, stderr);
61
+ const msg = maybeAny.message ?? "Unknown shell error";
62
+ const code = typeof maybeAny.code === "number" ? ` (exit code ${maybeAny.code})` : "";
63
+ return truncateOutput(`Command failed${code}: ${msg}\n\n${body}`);
64
+ }
65
+ return `Command failed: ${String(err)}`;
66
+ }
67
+ }
68
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/tools/shell.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export interface ToolExecutionContext {
2
+ abortSignal?: AbortSignal;
3
+ }
4
+ export type ToolHandler = (args: Record<string, unknown>, context: ToolExecutionContext) => Promise<string>;
5
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,MAAM,WAAW,GAAG,CACxB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,oBAAoB,KAC1B,OAAO,CAAC,MAAM,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "llm-agent-cli",
3
+ "version": "2.0.0",
4
+ "description": "Terminal AI agent powered by LLM-Router — read files, run commands, edit code, git integration, security scanning",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "llm-agent": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist/**/*",
12
+ "README.md"
13
+ ],
14
+ "engines": {
15
+ "node": ">=20.0.0"
16
+ },
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "prepublishOnly": "npm run build && npm test",
20
+ "dev": "node --loader ts-node/esm src/index.ts",
21
+ "start": "node dist/index.js",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest",
24
+ "test:coverage": "vitest run --coverage"
25
+ },
26
+ "keywords": [
27
+ "ai",
28
+ "agent",
29
+ "cli",
30
+ "llm",
31
+ "code-assistant",
32
+ "openai",
33
+ "anthropic",
34
+ "terminal"
35
+ ],
36
+ "license": "MIT",
37
+ "dependencies": {
38
+ "@inquirer/prompts": "^7.5.2",
39
+ "chalk": "^5.4.1",
40
+ "cli-highlight": "^2.1.11",
41
+ "commander": "^13.1.0",
42
+ "dotenv": "^16.5.0",
43
+ "ignore": "^7.0.5",
44
+ "marked": "^15.0.12",
45
+ "marked-terminal": "^7.3.0",
46
+ "ora": "^8.2.0",
47
+ "zod": "^3.24.2",
48
+ "zod-to-json-schema": "^3.24.5"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^22.15.3",
52
+ "@vitest/coverage-v8": "^3.1.3",
53
+ "typescript": "^5.8.3",
54
+ "vitest": "^3.1.3"
55
+ },
56
+ "publishConfig": {
57
+ "access": "public"
58
+ }
59
+ }