@llmtune/cli 0.1.0 → 0.1.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 (196) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/conversation.d.ts +42 -0
  3. package/dist/agent/conversation.js +105 -0
  4. package/dist/agent/loop.d.ts +19 -0
  5. package/dist/agent/loop.js +185 -0
  6. package/dist/agent/planner.d.ts +8 -0
  7. package/dist/agent/planner.js +43 -0
  8. package/dist/auth/client.d.ts +4 -0
  9. package/dist/auth/client.js +24 -0
  10. package/dist/auth/config.d.ts +21 -0
  11. package/dist/auth/config.js +83 -0
  12. package/dist/commands/chat.d.ts +5 -0
  13. package/dist/commands/chat.js +27 -0
  14. package/dist/commands/config.d.ts +2 -0
  15. package/dist/commands/config.js +37 -0
  16. package/dist/commands/login.d.ts +2 -0
  17. package/dist/commands/login.js +93 -0
  18. package/dist/commands/marketplace.d.ts +6 -0
  19. package/dist/commands/marketplace.js +213 -0
  20. package/dist/commands/models.d.ts +2 -0
  21. package/dist/commands/models.js +53 -0
  22. package/dist/compact/history-store.d.ts +29 -0
  23. package/dist/compact/history-store.js +110 -0
  24. package/dist/compact/microcompact.d.ts +10 -0
  25. package/dist/compact/microcompact.js +43 -0
  26. package/dist/compact/service.d.ts +13 -0
  27. package/dist/compact/service.js +156 -0
  28. package/dist/context/analyzer.d.ts +26 -0
  29. package/dist/context/analyzer.js +99 -0
  30. package/dist/context/builder.d.ts +13 -0
  31. package/dist/context/builder.js +144 -0
  32. package/dist/context/cache.d.ts +6 -0
  33. package/dist/context/cache.js +8 -0
  34. package/dist/context/git-context.d.ts +9 -0
  35. package/dist/context/git-context.js +49 -0
  36. package/dist/context/llmtune-md.d.ts +6 -0
  37. package/dist/context/llmtune-md.js +73 -0
  38. package/dist/context/workspace.d.ts +11 -0
  39. package/dist/context/workspace.js +115 -0
  40. package/dist/index.d.ts +3 -0
  41. package/dist/index.js +1 -1
  42. package/dist/marketplace/client.d.ts +52 -0
  43. package/dist/marketplace/client.js +86 -0
  44. package/dist/memory/files.d.ts +14 -0
  45. package/dist/memory/files.js +116 -0
  46. package/dist/memory/service.d.ts +22 -0
  47. package/dist/memory/service.js +146 -0
  48. package/dist/repl/repl.d.ts +8 -0
  49. package/dist/repl/repl.js +374 -0
  50. package/dist/skills/args.d.ts +10 -0
  51. package/dist/skills/args.js +37 -0
  52. package/dist/skills/frontmatter.d.ts +6 -0
  53. package/dist/skills/frontmatter.js +44 -0
  54. package/dist/skills/loader.d.ts +5 -0
  55. package/dist/skills/loader.js +59 -0
  56. package/dist/skills/registry.d.ts +27 -0
  57. package/dist/skills/registry.js +162 -0
  58. package/dist/skills/signing/signer.d.ts +19 -0
  59. package/dist/skills/signing/signer.js +110 -0
  60. package/dist/skills/trust.d.ts +11 -0
  61. package/dist/skills/trust.js +42 -0
  62. package/dist/telemetry/logger.d.ts +51 -0
  63. package/dist/telemetry/logger.js +135 -0
  64. package/dist/tools/permissions.d.ts +20 -0
  65. package/dist/tools/permissions.js +58 -0
  66. package/dist/tools/protocol.d.ts +22 -0
  67. package/dist/tools/protocol.js +3 -0
  68. package/dist/tools/registry.d.ts +20 -0
  69. package/dist/tools/registry.js +77 -0
  70. package/dist/tools/sandbox/docker.d.ts +16 -0
  71. package/dist/tools/sandbox/docker.js +240 -0
  72. package/dist/tools/sandbox/index.d.ts +18 -0
  73. package/dist/tools/sandbox/index.js +80 -0
  74. package/dist/tools/tools/ask-user.d.ts +3 -0
  75. package/dist/tools/tools/ask-user.js +56 -0
  76. package/dist/tools/tools/bash.d.ts +3 -0
  77. package/dist/tools/tools/bash.js +85 -0
  78. package/dist/tools/tools/edit.d.ts +3 -0
  79. package/dist/tools/tools/edit.js +138 -0
  80. package/dist/tools/tools/glob.d.ts +3 -0
  81. package/dist/tools/tools/glob.js +63 -0
  82. package/dist/tools/tools/grep.d.ts +3 -0
  83. package/dist/tools/tools/grep.js +148 -0
  84. package/dist/tools/tools/read.d.ts +3 -0
  85. package/dist/tools/tools/read.js +85 -0
  86. package/dist/tools/tools/web-fetch.d.ts +3 -0
  87. package/dist/tools/tools/web-fetch.js +142 -0
  88. package/dist/tools/tools/write.d.ts +3 -0
  89. package/dist/tools/tools/write.js +84 -0
  90. package/dist/tools/validation.d.ts +13 -0
  91. package/dist/tools/validation.js +142 -0
  92. package/dist/utils/markdown.d.ts +9 -0
  93. package/dist/utils/markdown.js +89 -0
  94. package/dist/utils/streaming.d.ts +10 -0
  95. package/dist/utils/streaming.js +63 -0
  96. package/dist/utils/tokens.d.ts +12 -0
  97. package/dist/utils/tokens.js +44 -0
  98. package/package.json +2 -2
  99. package/dist/agent/conversation.d.ts.map +0 -1
  100. package/dist/agent/loop.d.ts.map +0 -1
  101. package/dist/agent/planner.d.ts.map +0 -1
  102. package/dist/auth/client.d.ts.map +0 -1
  103. package/dist/auth/config.d.ts.map +0 -1
  104. package/dist/commands/chat.d.ts.map +0 -1
  105. package/dist/commands/config.d.ts.map +0 -1
  106. package/dist/commands/login.d.ts.map +0 -1
  107. package/dist/commands/marketplace.d.ts.map +0 -1
  108. package/dist/commands/models.d.ts.map +0 -1
  109. package/dist/compact/history-store.d.ts.map +0 -1
  110. package/dist/compact/microcompact.d.ts.map +0 -1
  111. package/dist/compact/service.d.ts.map +0 -1
  112. package/dist/context/analyzer.d.ts.map +0 -1
  113. package/dist/context/builder.d.ts.map +0 -1
  114. package/dist/context/cache.d.ts.map +0 -1
  115. package/dist/context/git-context.d.ts.map +0 -1
  116. package/dist/context/llmtune-md.d.ts.map +0 -1
  117. package/dist/context/workspace.d.ts.map +0 -1
  118. package/dist/index.d.ts.map +0 -1
  119. package/dist/marketplace/client.d.ts.map +0 -1
  120. package/dist/memory/files.d.ts.map +0 -1
  121. package/dist/memory/service.d.ts.map +0 -1
  122. package/dist/repl/repl.d.ts.map +0 -1
  123. package/dist/skills/args.d.ts.map +0 -1
  124. package/dist/skills/frontmatter.d.ts.map +0 -1
  125. package/dist/skills/loader.d.ts.map +0 -1
  126. package/dist/skills/registry.d.ts.map +0 -1
  127. package/dist/skills/signing/signer.d.ts.map +0 -1
  128. package/dist/skills/trust.d.ts.map +0 -1
  129. package/dist/telemetry/logger.d.ts.map +0 -1
  130. package/dist/tools/permissions.d.ts.map +0 -1
  131. package/dist/tools/protocol.d.ts.map +0 -1
  132. package/dist/tools/registry.d.ts.map +0 -1
  133. package/dist/tools/sandbox/docker.d.ts.map +0 -1
  134. package/dist/tools/sandbox/index.d.ts.map +0 -1
  135. package/dist/tools/tools/ask-user.d.ts.map +0 -1
  136. package/dist/tools/tools/bash.d.ts.map +0 -1
  137. package/dist/tools/tools/edit.d.ts.map +0 -1
  138. package/dist/tools/tools/glob.d.ts.map +0 -1
  139. package/dist/tools/tools/grep.d.ts.map +0 -1
  140. package/dist/tools/tools/read.d.ts.map +0 -1
  141. package/dist/tools/tools/web-fetch.d.ts.map +0 -1
  142. package/dist/tools/tools/write.d.ts.map +0 -1
  143. package/dist/tools/validation.d.ts.map +0 -1
  144. package/dist/utils/markdown.d.ts.map +0 -1
  145. package/dist/utils/streaming.d.ts.map +0 -1
  146. package/dist/utils/tokens.d.ts.map +0 -1
  147. package/src/agent/conversation.ts +0 -140
  148. package/src/agent/loop.ts +0 -215
  149. package/src/agent/planner.ts +0 -55
  150. package/src/auth/client.ts +0 -19
  151. package/src/auth/config.ts +0 -89
  152. package/src/commands/chat.ts +0 -28
  153. package/src/commands/config.ts +0 -36
  154. package/src/commands/login.ts +0 -63
  155. package/src/commands/marketplace.ts +0 -190
  156. package/src/commands/models.ts +0 -74
  157. package/src/compact/history-store.ts +0 -101
  158. package/src/compact/microcompact.ts +0 -49
  159. package/src/compact/service.ts +0 -154
  160. package/src/context/analyzer.ts +0 -127
  161. package/src/context/builder.ts +0 -123
  162. package/src/context/cache.ts +0 -11
  163. package/src/context/git-context.ts +0 -58
  164. package/src/context/llmtune-md.ts +0 -48
  165. package/src/context/workspace.ts +0 -139
  166. package/src/index.ts +0 -100
  167. package/src/marketplace/client.ts +0 -118
  168. package/src/memory/files.ts +0 -81
  169. package/src/memory/service.ts +0 -124
  170. package/src/repl/repl.ts +0 -400
  171. package/src/skills/args.ts +0 -35
  172. package/src/skills/builtin/explain-code/SKILL.md +0 -30
  173. package/src/skills/frontmatter.ts +0 -47
  174. package/src/skills/loader.ts +0 -25
  175. package/src/skills/registry.ts +0 -155
  176. package/src/skills/signing/signer.ts +0 -101
  177. package/src/skills/trust.ts +0 -50
  178. package/src/telemetry/logger.ts +0 -108
  179. package/src/tools/permissions.ts +0 -83
  180. package/src/tools/protocol.ts +0 -24
  181. package/src/tools/registry.ts +0 -93
  182. package/src/tools/sandbox/docker.ts +0 -225
  183. package/src/tools/sandbox/index.ts +0 -91
  184. package/src/tools/tools/ask-user.ts +0 -60
  185. package/src/tools/tools/bash.ts +0 -97
  186. package/src/tools/tools/edit.ts +0 -111
  187. package/src/tools/tools/glob.ts +0 -68
  188. package/src/tools/tools/grep.ts +0 -121
  189. package/src/tools/tools/read.ts +0 -57
  190. package/src/tools/tools/web-fetch.ts +0 -158
  191. package/src/tools/tools/write.ts +0 -52
  192. package/src/tools/validation.ts +0 -164
  193. package/src/utils/markdown.ts +0 -96
  194. package/src/utils/streaming.ts +0 -63
  195. package/src/utils/tokens.ts +0 -41
  196. package/tsconfig.json +0 -20
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ToolRegistry = void 0;
4
+ exports.createTool = createTool;
5
+ const validation_1 = require("./validation");
6
+ class ToolInstance {
7
+ def;
8
+ constructor(def) { this.def = def; }
9
+ spec() {
10
+ return {
11
+ name: this.def.name,
12
+ description: this.def.description,
13
+ inputSchema: this.def.inputSchema,
14
+ isReadOnly: this.def.isReadOnly,
15
+ isDestructive: this.def.isDestructive,
16
+ };
17
+ }
18
+ run(input, ctx) {
19
+ return this.def.run(input, ctx);
20
+ }
21
+ }
22
+ function createTool(def) {
23
+ return new ToolInstance(def);
24
+ }
25
+ class ToolRegistry {
26
+ tools = new Map();
27
+ register(tool) {
28
+ const spec = tool.spec();
29
+ const key = spec.name.toLowerCase();
30
+ if (this.tools.has(key)) {
31
+ throw new Error(`duplicate tool name: ${spec.name}`);
32
+ }
33
+ this.tools.set(key, tool);
34
+ }
35
+ listSpecs() {
36
+ return Array.from(this.tools.values()).map((t) => t.spec());
37
+ }
38
+ get(name) {
39
+ return this.tools.get(name.toLowerCase());
40
+ }
41
+ dispatch(name, input, ctx) {
42
+ const tool = this.get(name);
43
+ if (!tool) {
44
+ return { name, output: { error: `unknown tool: ${name}` }, isError: true };
45
+ }
46
+ const spec = tool.spec();
47
+ try {
48
+ (0, validation_1.validateJsonSchema)(input, spec.inputSchema);
49
+ }
50
+ catch (err) {
51
+ const msg = err instanceof Error ? err.message : String(err);
52
+ return { name: spec.name, output: { error: msg }, isError: true };
53
+ }
54
+ const result = tool.run(input, ctx);
55
+ if (result instanceof Promise) {
56
+ throw new Error("Async tools not supported in sync dispatch. Use dispatchAsync instead.");
57
+ }
58
+ return result;
59
+ }
60
+ async dispatchAsync(name, input, ctx) {
61
+ const tool = this.get(name);
62
+ if (!tool) {
63
+ return { name, output: { error: `unknown tool: ${name}` }, isError: true };
64
+ }
65
+ const spec = tool.spec();
66
+ try {
67
+ (0, validation_1.validateJsonSchema)(input, spec.inputSchema);
68
+ }
69
+ catch (err) {
70
+ const msg = err instanceof Error ? err.message : String(err);
71
+ return { name: spec.name, output: { error: msg }, isError: true };
72
+ }
73
+ return tool.run(input, ctx);
74
+ }
75
+ }
76
+ exports.ToolRegistry = ToolRegistry;
77
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1,16 @@
1
+ import type { ToolResult } from "../protocol";
2
+ export interface SandboxConfig {
3
+ enabled: boolean;
4
+ image: string;
5
+ timeoutMs: number;
6
+ readOnlyPaths: string[];
7
+ maxMemoryMB: number;
8
+ }
9
+ export declare const DEFAULT_SANDBOX_CONFIG: SandboxConfig;
10
+ export declare function configureSandbox(config: Partial<SandboxConfig>): void;
11
+ export declare function isSandboxEnabled(): boolean;
12
+ export declare function isDockerAvailable(): Promise<boolean>;
13
+ export declare function ensureSandboxImage(): Promise<boolean>;
14
+ export declare function runInSandbox(command: string, cwd: string): Promise<ToolResult>;
15
+ export declare function writeFileInSandbox(filePath: string, content: string, cwd: string): Promise<ToolResult>;
16
+ //# sourceMappingURL=docker.d.ts.map
@@ -0,0 +1,240 @@
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.DEFAULT_SANDBOX_CONFIG = void 0;
37
+ exports.configureSandbox = configureSandbox;
38
+ exports.isSandboxEnabled = isSandboxEnabled;
39
+ exports.isDockerAvailable = isDockerAvailable;
40
+ exports.ensureSandboxImage = ensureSandboxImage;
41
+ exports.runInSandbox = runInSandbox;
42
+ exports.writeFileInSandbox = writeFileInSandbox;
43
+ /**
44
+ * Docker-based tool sandbox for enterprise deployments.
45
+ * Isolates bash and file write operations inside a Docker container
46
+ * to prevent accidental or malicious damage to the host system.
47
+ */
48
+ const child_process_1 = require("child_process");
49
+ const util_1 = require("util");
50
+ const path = __importStar(require("path"));
51
+ const fs = __importStar(require("fs"));
52
+ const os = __importStar(require("os"));
53
+ const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
54
+ const SANDBOX_IMAGE = "llmtune-sandbox:latest";
55
+ const SANDBOX_WORKDIR = "/workspace";
56
+ const EXECUTION_TIMEOUT_MS = 60_000;
57
+ const MAX_OUTPUT_BYTES = 100_000;
58
+ exports.DEFAULT_SANDBOX_CONFIG = {
59
+ enabled: false,
60
+ image: SANDBOX_IMAGE,
61
+ timeoutMs: EXECUTION_TIMEOUT_MS,
62
+ readOnlyPaths: [],
63
+ maxMemoryMB: 512,
64
+ };
65
+ let sandboxConfig = { ...exports.DEFAULT_SANDBOX_CONFIG };
66
+ function configureSandbox(config) {
67
+ sandboxConfig = { ...sandboxConfig, ...config };
68
+ }
69
+ function isSandboxEnabled() {
70
+ return sandboxConfig.enabled;
71
+ }
72
+ async function isDockerAvailable() {
73
+ try {
74
+ const { stdout } = await execFileAsync("docker", ["--version"], {
75
+ timeout: 5000,
76
+ });
77
+ return /docker/i.test(stdout);
78
+ }
79
+ catch {
80
+ return false;
81
+ }
82
+ }
83
+ async function ensureSandboxImage() {
84
+ try {
85
+ const { stdout } = await execFileAsync("docker", ["images", "-q", sandboxConfig.image], {
86
+ timeout: 10000,
87
+ });
88
+ if (stdout.trim())
89
+ return true;
90
+ // Pull the image if not found
91
+ console.log(`Pulling sandbox image: ${sandboxConfig.image}...`);
92
+ await execFileAsync("docker", ["pull", sandboxConfig.image], {
93
+ timeout: 120_000,
94
+ });
95
+ return true;
96
+ }
97
+ catch {
98
+ return false;
99
+ }
100
+ }
101
+ async function runInSandbox(command, cwd) {
102
+ if (!sandboxConfig.enabled) {
103
+ return {
104
+ name: "sandbox",
105
+ output: { error: "Sandbox is not enabled" },
106
+ isError: true,
107
+ };
108
+ }
109
+ const dockerAvailable = await isDockerAvailable();
110
+ if (!dockerAvailable) {
111
+ return {
112
+ name: "sandbox",
113
+ output: { error: "Docker is not available. Install Docker to use sandbox mode." },
114
+ isError: true,
115
+ };
116
+ }
117
+ const workspaceMount = `${path.resolve(cwd)}:${SANDBOX_WORKDIR}`;
118
+ const memoryLimit = `${sandboxConfig.maxMemoryMB}m`;
119
+ const timeout = Math.min(sandboxConfig.timeoutMs, 120_000);
120
+ const args = [
121
+ "run",
122
+ "--rm",
123
+ "--network", "none",
124
+ "--memory", memoryLimit,
125
+ "--cpus", "1",
126
+ "--timeout", String(Math.ceil(timeout / 1000)),
127
+ "-v", `${workspaceMount}:ro`,
128
+ "--workdir", SANDBOX_WORKDIR,
129
+ sandboxConfig.image,
130
+ "sh", "-c", command,
131
+ ];
132
+ try {
133
+ const { stdout, stderr } = await execFileAsync("docker", args, {
134
+ timeout: timeout + 10_000,
135
+ maxBuffer: MAX_OUTPUT_BYTES,
136
+ });
137
+ let output = "";
138
+ if (stdout)
139
+ output += truncateOutput(stdout);
140
+ if (stderr) {
141
+ output += "\n--- stderr ---\n";
142
+ output += truncateOutput(stderr);
143
+ }
144
+ return {
145
+ name: "sandbox",
146
+ output: {
147
+ stdout: output.trim(),
148
+ exit_code: 0,
149
+ sandboxed: true,
150
+ },
151
+ isError: false,
152
+ };
153
+ }
154
+ catch (err) {
155
+ const execErr = err;
156
+ let output = "";
157
+ if (execErr.stdout)
158
+ output += truncateOutput(execErr.stdout);
159
+ if (execErr.stderr) {
160
+ output += "\n--- stderr ---\n";
161
+ output += truncateOutput(execErr.stderr);
162
+ }
163
+ if (execErr.killed) {
164
+ output += `\n--- Process killed (timeout or memory limit) ---`;
165
+ }
166
+ return {
167
+ name: "sandbox",
168
+ output: {
169
+ stdout: output.trim(),
170
+ exit_code: typeof execErr.code === "number" ? execErr.code : 1,
171
+ sandboxed: true,
172
+ timed_out: execErr.killed ?? false,
173
+ },
174
+ isError: true,
175
+ };
176
+ }
177
+ }
178
+ async function writeFileInSandbox(filePath, content, cwd) {
179
+ if (!sandboxConfig.enabled) {
180
+ return {
181
+ name: "sandbox",
182
+ output: { error: "Sandbox is not enabled" },
183
+ isError: true,
184
+ };
185
+ }
186
+ // Write to a temp file on host, then copy into container
187
+ const tmpDir = path.join(os.tmpdir(), "llmtune-sandbox");
188
+ fs.mkdirSync(tmpDir, { recursive: true });
189
+ const tmpFile = path.join(tmpDir, `write-${Date.now()}.tmp`);
190
+ fs.writeFileSync(tmpFile, content, "utf-8");
191
+ try {
192
+ const absTarget = path.resolve(cwd, filePath);
193
+ const containerPath = `${SANDBOX_WORKDIR}/${path.relative(cwd, absTarget).replace(/\\/g, "/")}`;
194
+ const workspaceMount = `${path.resolve(cwd)}:${SANDBOX_WORKDIR}`;
195
+ const dockerArgs = [
196
+ "run",
197
+ "--rm",
198
+ "--network", "none",
199
+ "--memory", `${sandboxConfig.maxMemoryMB}m`,
200
+ "-v", `${workspaceMount}`,
201
+ "-v", `${tmpFile}:/tmp/write-content.tmp:ro`,
202
+ "--workdir", SANDBOX_WORKDIR,
203
+ sandboxConfig.image,
204
+ "sh", "-c", `mkdir -p "$(dirname '${containerPath}')" && cp /tmp/write-content.tmp '${containerPath}'`,
205
+ ];
206
+ await execFileAsync("docker", dockerArgs, { timeout: 30_000 });
207
+ return {
208
+ name: "sandbox",
209
+ output: {
210
+ type: "text",
211
+ filePath,
212
+ bytesWritten: Buffer.byteLength(content, "utf-8"),
213
+ sandboxed: true,
214
+ },
215
+ isError: false,
216
+ };
217
+ }
218
+ catch (err) {
219
+ return {
220
+ name: "sandbox",
221
+ output: { error: `Sandbox write failed: ${err.message}` },
222
+ isError: true,
223
+ };
224
+ }
225
+ finally {
226
+ try {
227
+ fs.unlinkSync(tmpFile);
228
+ }
229
+ catch {
230
+ // cleanup failure is non-critical
231
+ }
232
+ }
233
+ }
234
+ function truncateOutput(output) {
235
+ if (output.length > 50_000) {
236
+ return output.slice(0, 50_000) + "\n... (truncated)";
237
+ }
238
+ return output;
239
+ }
240
+ //# sourceMappingURL=docker.js.map
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Sandbox manager: decides when to use Docker isolation vs local execution.
3
+ *
4
+ * Modes:
5
+ * - "off" — all tools run locally (default)
6
+ * - "available" — use Docker when available, fall back to local
7
+ * - "required" — require Docker for destructive tools (enterprise mode)
8
+ */
9
+ import type { ToolResult } from "../protocol";
10
+ export type SandboxMode = "off" | "available" | "required";
11
+ export declare function getSandboxMode(): SandboxMode;
12
+ export declare function setSandboxMode(mode: SandboxMode): void;
13
+ export declare function isDockerAvailable(): boolean;
14
+ /**
15
+ * Execute a bash command, optionally in a Docker sandbox.
16
+ */
17
+ export declare function sandboxedExec(command: string, cwd: string, timeout: number): Promise<ToolResult>;
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSandboxMode = getSandboxMode;
4
+ exports.setSandboxMode = setSandboxMode;
5
+ exports.isDockerAvailable = isDockerAvailable;
6
+ exports.sandboxedExec = sandboxedExec;
7
+ const docker_1 = require("./docker");
8
+ let sandboxMode = "off";
9
+ let dockerAvailable = null;
10
+ function getSandboxMode() {
11
+ return sandboxMode;
12
+ }
13
+ function setSandboxMode(mode) {
14
+ sandboxMode = mode;
15
+ dockerAvailable = null; // re-check on next use
16
+ }
17
+ function isDockerAvailable() {
18
+ if (dockerAvailable !== null)
19
+ return dockerAvailable;
20
+ // Quick check: can we run `docker info`?
21
+ try {
22
+ const { execSync } = require("child_process");
23
+ execSync("docker info", { timeout: 3000, stdio: "pipe" });
24
+ dockerAvailable = true;
25
+ }
26
+ catch {
27
+ dockerAvailable = false;
28
+ }
29
+ return dockerAvailable;
30
+ }
31
+ /**
32
+ * Execute a bash command, optionally in a Docker sandbox.
33
+ */
34
+ async function sandboxedExec(command, cwd, timeout) {
35
+ if (sandboxMode === "off") {
36
+ return localExec(command, cwd, timeout);
37
+ }
38
+ if (sandboxMode === "available" && !isDockerAvailable()) {
39
+ return localExec(command, cwd, timeout);
40
+ }
41
+ if (sandboxMode === "required" && !isDockerAvailable()) {
42
+ return {
43
+ name: "bash",
44
+ output: {
45
+ error: "Enterprise mode requires Docker but Docker is not available. Install Docker or disable enterprise mode.",
46
+ },
47
+ isError: true,
48
+ };
49
+ }
50
+ return (0, docker_1.runInSandbox)(command, cwd);
51
+ }
52
+ function localExec(command, cwd, timeout) {
53
+ const { execSync } = require("child_process");
54
+ try {
55
+ const stdout = execSync(command, {
56
+ cwd,
57
+ timeout,
58
+ maxBuffer: 1024 * 1024 * 10,
59
+ encoding: "utf-8",
60
+ shell: process.platform === "win32" ? "cmd.exe" : "/bin/bash",
61
+ });
62
+ return { name: "bash", output: { stdout: stdout || "(no output)", exitCode: 0 }, isError: false };
63
+ }
64
+ catch (err) {
65
+ const e = err;
66
+ let output = "";
67
+ if (e.stdout)
68
+ output += String(e.stdout).slice(0, 50_000);
69
+ if (e.stderr)
70
+ output += "\n--- stderr ---\n" + String(e.stderr).slice(0, 50_000);
71
+ if (e.killed)
72
+ output += `\n--- Process timed out after ${timeout}ms ---`;
73
+ return {
74
+ name: "bash",
75
+ output: { stdout: output.trim(), exitCode: e.status ?? 1 },
76
+ isError: true,
77
+ };
78
+ }
79
+ }
80
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
1
+ import type { Tool } from "../protocol";
2
+ export declare const askUserTool: Tool;
3
+ //# sourceMappingURL=ask-user.d.ts.map
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.askUserTool = void 0;
4
+ const readline_1 = require("readline");
5
+ exports.askUserTool = {
6
+ spec() {
7
+ return {
8
+ name: "ask_user",
9
+ description: "Ask the user a question and wait for their response. Use when you need clarification, confirmation, or additional information before proceeding.",
10
+ inputSchema: {
11
+ type: "object",
12
+ properties: {
13
+ question: {
14
+ type: "string",
15
+ description: "The question to ask the user",
16
+ },
17
+ options: {
18
+ type: "array",
19
+ items: { type: "string" },
20
+ description: "Optional list of choices for the user to pick from",
21
+ },
22
+ },
23
+ required: ["question"],
24
+ },
25
+ isReadOnly: true,
26
+ };
27
+ },
28
+ async run(input, _ctx) {
29
+ const question = String(input.question ?? "");
30
+ if (!question) {
31
+ return { name: "ask_user", output: { error: "question is required" }, isError: true };
32
+ }
33
+ const options = Array.isArray(input.options) ? input.options.map(String) : [];
34
+ if (options.length > 0) {
35
+ console.log(`\n ${question}`);
36
+ options.forEach((opt, i) => console.log(` ${i + 1}. ${opt}`));
37
+ console.log();
38
+ }
39
+ else {
40
+ console.log(`\n ${question}\n`);
41
+ }
42
+ const rl = (0, readline_1.createInterface)({ input: process.stdin, output: process.stdout });
43
+ const answer = await new Promise((resolve) => {
44
+ rl.question(" > ", (ans) => {
45
+ rl.close();
46
+ resolve(ans.trim());
47
+ });
48
+ });
49
+ return {
50
+ name: "ask_user",
51
+ output: { question, answer, selectedOption: options.length > 0 ? parseInt(answer) || 0 : undefined },
52
+ isError: false,
53
+ };
54
+ },
55
+ };
56
+ //# sourceMappingURL=ask-user.js.map
@@ -0,0 +1,3 @@
1
+ import type { Tool } from "../protocol";
2
+ export declare const bashTool: Tool;
3
+ //# sourceMappingURL=bash.d.ts.map
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.bashTool = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const util_1 = require("util");
6
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
7
+ const MAX_OUTPUT = 50_000;
8
+ const TIMEOUT_MS = 120_000;
9
+ exports.bashTool = {
10
+ spec() {
11
+ return {
12
+ name: "bash",
13
+ description: "Execute a shell command. Returns stdout, stderr, and exit code. Use for running builds, tests, git commands, and other shell operations.",
14
+ inputSchema: {
15
+ type: "object",
16
+ properties: {
17
+ command: {
18
+ type: "string",
19
+ description: "The command to execute",
20
+ },
21
+ timeout: {
22
+ type: "number",
23
+ description: "Optional timeout in ms (default 120000, max 300000)",
24
+ },
25
+ },
26
+ required: ["command"],
27
+ },
28
+ isReadOnly: false,
29
+ isDestructive: true,
30
+ };
31
+ },
32
+ async run(input, _ctx) {
33
+ const command = String(input.command ?? "");
34
+ const timeout = Math.min(typeof input.timeout === "number" ? input.timeout : TIMEOUT_MS, 300_000);
35
+ if (!command.trim()) {
36
+ return { name: "bash", output: { error: "command is required" }, isError: true };
37
+ }
38
+ try {
39
+ const { stdout, stderr } = await execAsync(command, {
40
+ maxBuffer: 1024 * 1024 * 10,
41
+ timeout,
42
+ shell: process.platform === "win32" ? "cmd" : "/bin/bash",
43
+ });
44
+ let output = "";
45
+ if (stdout) {
46
+ output += stdout.length > MAX_OUTPUT
47
+ ? stdout.slice(0, MAX_OUTPUT) + "\n... (truncated)"
48
+ : stdout;
49
+ }
50
+ if (stderr) {
51
+ output += "\n--- stderr ---\n";
52
+ output += stderr.length > MAX_OUTPUT
53
+ ? stderr.slice(0, MAX_OUTPUT) + "\n... (truncated)"
54
+ : stderr;
55
+ }
56
+ return {
57
+ name: "bash",
58
+ output: { stdout: output.trim(), exit_code: 0 },
59
+ isError: false,
60
+ };
61
+ }
62
+ catch (err) {
63
+ const e = err;
64
+ const stdout = e.stdout || "";
65
+ const stderr = e.stderr || "";
66
+ const exitCode = typeof e.code === "number" ? e.code : 1;
67
+ let output = "";
68
+ if (stdout)
69
+ output += stdout.slice(0, MAX_OUTPUT);
70
+ if (stderr) {
71
+ output += "\n--- stderr ---\n";
72
+ output += stderr.slice(0, MAX_OUTPUT);
73
+ }
74
+ if (e.killed) {
75
+ output += `\n--- Process timed out after ${timeout}ms ---`;
76
+ }
77
+ return {
78
+ name: "bash",
79
+ output: { stdout: output.trim(), exit_code: exitCode },
80
+ isError: true,
81
+ };
82
+ }
83
+ },
84
+ };
85
+ //# sourceMappingURL=bash.js.map
@@ -0,0 +1,3 @@
1
+ import type { Tool } from "../protocol";
2
+ export declare const editTool: Tool;
3
+ //# sourceMappingURL=edit.d.ts.map