agentool 0.0.1 → 1.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 (115) hide show
  1. package/README.md +627 -52
  2. package/dist/ask-user/index.cjs +8 -0
  3. package/dist/ask-user/index.d.cts +68 -0
  4. package/dist/ask-user/index.d.ts +68 -0
  5. package/dist/ask-user/index.js +8 -0
  6. package/dist/bash/index.cjs +8 -0
  7. package/dist/bash/index.d.cts +63 -0
  8. package/dist/bash/index.d.ts +63 -0
  9. package/dist/bash/index.js +8 -0
  10. package/dist/chunk-3EPGFWZV.cjs +30 -0
  11. package/dist/chunk-3VO6NETR.cjs +79 -0
  12. package/dist/chunk-4YI2H55A.js +142 -0
  13. package/dist/chunk-5NW4OGRI.cjs +99 -0
  14. package/dist/chunk-6MDPYALY.js +196 -0
  15. package/dist/chunk-6PQLFDGT.js +117 -0
  16. package/dist/chunk-7QL4BQCH.js +40 -0
  17. package/dist/chunk-CAEVLIQB.cjs +117 -0
  18. package/dist/chunk-CGTPF6IS.js +90 -0
  19. package/dist/chunk-EA3YV7ZG.js +79 -0
  20. package/dist/chunk-FAEGCFTO.js +136 -0
  21. package/dist/chunk-FV2R5FFQ.cjs +102 -0
  22. package/dist/chunk-FW3UJ622.cjs +59 -0
  23. package/dist/chunk-G3ITTPGX.js +99 -0
  24. package/dist/chunk-HDKXSKMO.js +30 -0
  25. package/dist/chunk-HZAQRHBT.js +99 -0
  26. package/dist/chunk-I3ONDY7P.js +46 -0
  27. package/dist/chunk-I6KFFQPV.cjs +58 -0
  28. package/dist/chunk-IMZQ7ELK.cjs +196 -0
  29. package/dist/chunk-JCTBB7H2.cjs +40 -0
  30. package/dist/chunk-K77GC2QI.js +59 -0
  31. package/dist/chunk-LPV5CN2K.js +58 -0
  32. package/dist/chunk-MF7CJVIZ.js +40 -0
  33. package/dist/chunk-MIYA7TNR.cjs +123 -0
  34. package/dist/chunk-MJCAXASI.js +123 -0
  35. package/dist/chunk-MXFW3XY6.cjs +73 -0
  36. package/dist/chunk-ONBH74ZV.cjs +90 -0
  37. package/dist/chunk-OXLQ7QVL.cjs +40 -0
  38. package/dist/chunk-QEJV2KZ4.cjs +159 -0
  39. package/dist/chunk-QZ5GS6HW.cjs +46 -0
  40. package/dist/chunk-S6QEY7UY.js +73 -0
  41. package/dist/chunk-SUSAPI5W.cjs +142 -0
  42. package/dist/chunk-TBVHHF3H.cjs +47 -0
  43. package/dist/chunk-U2YMJM25.cjs +115 -0
  44. package/dist/chunk-VLNDEVKS.js +102 -0
  45. package/dist/chunk-XKG2A3EW.js +159 -0
  46. package/dist/chunk-XLD2Y3SS.cjs +136 -0
  47. package/dist/chunk-Y7KOKDFP.js +115 -0
  48. package/dist/chunk-YPPPGGLA.cjs +99 -0
  49. package/dist/chunk-ZHCMEQJJ.js +47 -0
  50. package/dist/context-compaction/index.cjs +8 -0
  51. package/dist/context-compaction/index.d.cts +77 -0
  52. package/dist/context-compaction/index.d.ts +77 -0
  53. package/dist/context-compaction/index.js +8 -0
  54. package/dist/diff/index.cjs +9 -0
  55. package/dist/diff/index.d.cts +72 -0
  56. package/dist/diff/index.d.ts +72 -0
  57. package/dist/diff/index.js +9 -0
  58. package/dist/edit/index.cjs +10 -0
  59. package/dist/edit/index.d.cts +53 -0
  60. package/dist/edit/index.d.ts +53 -0
  61. package/dist/edit/index.js +10 -0
  62. package/dist/glob/index.cjs +10 -0
  63. package/dist/glob/index.d.cts +47 -0
  64. package/dist/glob/index.d.ts +47 -0
  65. package/dist/glob/index.js +10 -0
  66. package/dist/grep/index.cjs +10 -0
  67. package/dist/grep/index.d.cts +50 -0
  68. package/dist/grep/index.d.ts +50 -0
  69. package/dist/grep/index.js +10 -0
  70. package/dist/http-request/index.cjs +8 -0
  71. package/dist/http-request/index.d.cts +60 -0
  72. package/dist/http-request/index.d.ts +60 -0
  73. package/dist/http-request/index.js +8 -0
  74. package/dist/index.cjs +102 -0
  75. package/dist/index.d.cts +18 -0
  76. package/dist/index.d.ts +18 -0
  77. package/dist/index.js +102 -0
  78. package/dist/lsp/index.cjs +10 -0
  79. package/dist/lsp/index.d.cts +38 -0
  80. package/dist/lsp/index.d.ts +38 -0
  81. package/dist/lsp/index.js +10 -0
  82. package/dist/memory/index.cjs +9 -0
  83. package/dist/memory/index.d.cts +63 -0
  84. package/dist/memory/index.d.ts +63 -0
  85. package/dist/memory/index.js +9 -0
  86. package/dist/multi-edit/index.cjs +11 -0
  87. package/dist/multi-edit/index.d.cts +72 -0
  88. package/dist/multi-edit/index.d.ts +72 -0
  89. package/dist/multi-edit/index.js +11 -0
  90. package/dist/read/index.cjs +10 -0
  91. package/dist/read/index.d.cts +67 -0
  92. package/dist/read/index.d.ts +67 -0
  93. package/dist/read/index.js +10 -0
  94. package/dist/sleep/index.cjs +8 -0
  95. package/dist/sleep/index.d.cts +60 -0
  96. package/dist/sleep/index.d.ts +60 -0
  97. package/dist/sleep/index.js +8 -0
  98. package/dist/task/index.cjs +8 -0
  99. package/dist/task/index.d.cts +67 -0
  100. package/dist/task/index.d.ts +67 -0
  101. package/dist/task/index.js +8 -0
  102. package/dist/types-3QPDuCXN.d.cts +45 -0
  103. package/dist/types-3QPDuCXN.d.ts +45 -0
  104. package/dist/web-fetch/index.cjs +8 -0
  105. package/dist/web-fetch/index.d.cts +56 -0
  106. package/dist/web-fetch/index.d.ts +56 -0
  107. package/dist/web-fetch/index.js +8 -0
  108. package/dist/write/index.cjs +10 -0
  109. package/dist/write/index.d.cts +47 -0
  110. package/dist/write/index.d.ts +47 -0
  111. package/dist/write/index.js +10 -0
  112. package/package.json +145 -20
  113. package/dist/core/index.d.ts +0 -20
  114. package/dist/core/index.js +0 -1
  115. package/dist/core/index.js.map +0 -1
@@ -0,0 +1,8 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+ var _chunk3EPGFWZVcjs = require('../chunk-3EPGFWZV.cjs');
5
+
6
+
7
+
8
+ exports.askUser = _chunk3EPGFWZVcjs.askUser; exports.createAskUser = _chunk3EPGFWZVcjs.createAskUser;
@@ -0,0 +1,68 @@
1
+ import * as ai from 'ai';
2
+ import { B as BaseToolConfig } from '../types-3QPDuCXN.cjs';
3
+
4
+ /**
5
+ * Configuration for the ask-user tool.
6
+ * Extends {@link BaseToolConfig} with an optional callback for receiving user input.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import type { AskUserConfig } from 'agentool/ask-user';
11
+ * const config: AskUserConfig = {
12
+ * onQuestion: async (question) => prompt(question) ?? '',
13
+ * };
14
+ * ```
15
+ */
16
+ interface AskUserConfig extends BaseToolConfig {
17
+ /**
18
+ * Callback invoked when the tool needs user input.
19
+ * Must be provided for the tool to work.
20
+ *
21
+ * @param question - The question to present to the user
22
+ * @param options - Optional list of suggested response options
23
+ * @returns The user's response string
24
+ */
25
+ onQuestion?: (question: string, options?: string[]) => Promise<string>;
26
+ }
27
+ /**
28
+ * Creates an ask-user tool instance with the given configuration.
29
+ * The tool pauses agent execution and prompts the user for input via the
30
+ * configured {@link AskUserConfig.onQuestion} callback.
31
+ *
32
+ * Execute never throws. Errors are returned as descriptive strings.
33
+ *
34
+ * @param config - Tool configuration with optional onQuestion callback
35
+ * @returns An AI SDK tool that asks the user a question and returns their response
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * import { createAskUser } from 'agentool/ask-user';
40
+ * const askUser = createAskUser({
41
+ * onQuestion: async (q, opts) => {
42
+ * console.log(q, opts);
43
+ * return 'user reply';
44
+ * },
45
+ * });
46
+ * ```
47
+ */
48
+ declare function createAskUser(config?: AskUserConfig): ai.Tool<{
49
+ question: string;
50
+ options?: string[] | undefined;
51
+ }, string>;
52
+ /**
53
+ * Default ask-user tool instance with no callback configured.
54
+ * Calling execute on this instance returns an error string prompting the
55
+ * consumer to provide an {@link AskUserConfig.onQuestion} callback.
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * import { askUser } from 'agentool/ask-user';
60
+ * // Typically you'd use createAskUser() with a callback instead.
61
+ * ```
62
+ */
63
+ declare const askUser: ai.Tool<{
64
+ question: string;
65
+ options?: string[] | undefined;
66
+ }, string>;
67
+
68
+ export { type AskUserConfig, askUser, createAskUser };
@@ -0,0 +1,68 @@
1
+ import * as ai from 'ai';
2
+ import { B as BaseToolConfig } from '../types-3QPDuCXN.js';
3
+
4
+ /**
5
+ * Configuration for the ask-user tool.
6
+ * Extends {@link BaseToolConfig} with an optional callback for receiving user input.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import type { AskUserConfig } from 'agentool/ask-user';
11
+ * const config: AskUserConfig = {
12
+ * onQuestion: async (question) => prompt(question) ?? '',
13
+ * };
14
+ * ```
15
+ */
16
+ interface AskUserConfig extends BaseToolConfig {
17
+ /**
18
+ * Callback invoked when the tool needs user input.
19
+ * Must be provided for the tool to work.
20
+ *
21
+ * @param question - The question to present to the user
22
+ * @param options - Optional list of suggested response options
23
+ * @returns The user's response string
24
+ */
25
+ onQuestion?: (question: string, options?: string[]) => Promise<string>;
26
+ }
27
+ /**
28
+ * Creates an ask-user tool instance with the given configuration.
29
+ * The tool pauses agent execution and prompts the user for input via the
30
+ * configured {@link AskUserConfig.onQuestion} callback.
31
+ *
32
+ * Execute never throws. Errors are returned as descriptive strings.
33
+ *
34
+ * @param config - Tool configuration with optional onQuestion callback
35
+ * @returns An AI SDK tool that asks the user a question and returns their response
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * import { createAskUser } from 'agentool/ask-user';
40
+ * const askUser = createAskUser({
41
+ * onQuestion: async (q, opts) => {
42
+ * console.log(q, opts);
43
+ * return 'user reply';
44
+ * },
45
+ * });
46
+ * ```
47
+ */
48
+ declare function createAskUser(config?: AskUserConfig): ai.Tool<{
49
+ question: string;
50
+ options?: string[] | undefined;
51
+ }, string>;
52
+ /**
53
+ * Default ask-user tool instance with no callback configured.
54
+ * Calling execute on this instance returns an error string prompting the
55
+ * consumer to provide an {@link AskUserConfig.onQuestion} callback.
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * import { askUser } from 'agentool/ask-user';
60
+ * // Typically you'd use createAskUser() with a callback instead.
61
+ * ```
62
+ */
63
+ declare const askUser: ai.Tool<{
64
+ question: string;
65
+ options?: string[] | undefined;
66
+ }, string>;
67
+
68
+ export { type AskUserConfig, askUser, createAskUser };
@@ -0,0 +1,8 @@
1
+ import {
2
+ askUser,
3
+ createAskUser
4
+ } from "../chunk-HDKXSKMO.js";
5
+ export {
6
+ askUser,
7
+ createAskUser
8
+ };
@@ -0,0 +1,8 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+ var _chunkSUSAPI5Wcjs = require('../chunk-SUSAPI5W.cjs');
5
+
6
+
7
+
8
+ exports.bash = _chunkSUSAPI5Wcjs.bash; exports.createBash = _chunkSUSAPI5Wcjs.createBash;
@@ -0,0 +1,63 @@
1
+ import * as ai from 'ai';
2
+ import { T as TimeoutConfig } from '../types-3QPDuCXN.cjs';
3
+
4
+ /**
5
+ * Configuration for the bash tool.
6
+ * Extends {@link TimeoutConfig} with an optional shell binary path.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import type { BashConfig } from 'agentool/bash';
11
+ * const config: BashConfig = { cwd: '/my/project', timeout: 30000, shell: '/bin/zsh' };
12
+ * ```
13
+ */
14
+ interface BashConfig extends TimeoutConfig {
15
+ /** Shell binary to use. Defaults to `$SHELL` or `/bin/bash`. */
16
+ shell?: string;
17
+ }
18
+ /**
19
+ * Creates a bash tool that executes shell commands via {@link executeShell}.
20
+ *
21
+ * The tool spawns the configured shell with `-c` and the given command string.
22
+ * Timeout escalation follows SIGTERM then SIGKILL after a 5-second grace period.
23
+ * Execute never throws; errors are returned as descriptive strings.
24
+ *
25
+ * @param config - Optional configuration for cwd, timeout, and shell binary.
26
+ * @returns A Vercel AI SDK tool with `description`, `parameters`, and `execute`.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * import { createBash } from 'agentool/bash';
31
+ *
32
+ * const bashTool = createBash({ cwd: '/my/project', timeout: 60000 });
33
+ * const result = await bashTool.execute(
34
+ * { command: 'ls -la' },
35
+ * { toolCallId: 'id', messages: [] },
36
+ * );
37
+ * ```
38
+ */
39
+ declare function createBash(config?: BashConfig): ai.Tool<{
40
+ command: string;
41
+ timeout?: number | undefined;
42
+ description?: string | undefined;
43
+ }, string>;
44
+ /**
45
+ * Default bash tool instance using the current working directory,
46
+ * a 120-second timeout, and the system default shell.
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * import { bash } from 'agentool/bash';
51
+ * const result = await bash.execute(
52
+ * { command: 'echo hello' },
53
+ * { toolCallId: 'id', messages: [] },
54
+ * );
55
+ * ```
56
+ */
57
+ declare const bash: ai.Tool<{
58
+ command: string;
59
+ timeout?: number | undefined;
60
+ description?: string | undefined;
61
+ }, string>;
62
+
63
+ export { type BashConfig, bash, createBash };
@@ -0,0 +1,63 @@
1
+ import * as ai from 'ai';
2
+ import { T as TimeoutConfig } from '../types-3QPDuCXN.js';
3
+
4
+ /**
5
+ * Configuration for the bash tool.
6
+ * Extends {@link TimeoutConfig} with an optional shell binary path.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import type { BashConfig } from 'agentool/bash';
11
+ * const config: BashConfig = { cwd: '/my/project', timeout: 30000, shell: '/bin/zsh' };
12
+ * ```
13
+ */
14
+ interface BashConfig extends TimeoutConfig {
15
+ /** Shell binary to use. Defaults to `$SHELL` or `/bin/bash`. */
16
+ shell?: string;
17
+ }
18
+ /**
19
+ * Creates a bash tool that executes shell commands via {@link executeShell}.
20
+ *
21
+ * The tool spawns the configured shell with `-c` and the given command string.
22
+ * Timeout escalation follows SIGTERM then SIGKILL after a 5-second grace period.
23
+ * Execute never throws; errors are returned as descriptive strings.
24
+ *
25
+ * @param config - Optional configuration for cwd, timeout, and shell binary.
26
+ * @returns A Vercel AI SDK tool with `description`, `parameters`, and `execute`.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * import { createBash } from 'agentool/bash';
31
+ *
32
+ * const bashTool = createBash({ cwd: '/my/project', timeout: 60000 });
33
+ * const result = await bashTool.execute(
34
+ * { command: 'ls -la' },
35
+ * { toolCallId: 'id', messages: [] },
36
+ * );
37
+ * ```
38
+ */
39
+ declare function createBash(config?: BashConfig): ai.Tool<{
40
+ command: string;
41
+ timeout?: number | undefined;
42
+ description?: string | undefined;
43
+ }, string>;
44
+ /**
45
+ * Default bash tool instance using the current working directory,
46
+ * a 120-second timeout, and the system default shell.
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * import { bash } from 'agentool/bash';
51
+ * const result = await bash.execute(
52
+ * { command: 'echo hello' },
53
+ * { toolCallId: 'id', messages: [] },
54
+ * );
55
+ * ```
56
+ */
57
+ declare const bash: ai.Tool<{
58
+ command: string;
59
+ timeout?: number | undefined;
60
+ description?: string | undefined;
61
+ }, string>;
62
+
63
+ export { type BashConfig, bash, createBash };
@@ -0,0 +1,8 @@
1
+ import {
2
+ bash,
3
+ createBash
4
+ } from "../chunk-4YI2H55A.js";
5
+ export {
6
+ bash,
7
+ createBash
8
+ };
@@ -0,0 +1,30 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/ask-user/index.ts
2
+ var _ai = require('ai');
3
+ var _zod = require('zod');
4
+ function createAskUser(config = {}) {
5
+ return _ai.tool.call(void 0, {
6
+ description: "Ask the user a question and wait for their response. Use this when you need clarification, confirmation, or additional information from the user before proceeding.",
7
+ inputSchema: _zod.z.object({
8
+ question: _zod.z.string().describe("The question to ask the user"),
9
+ options: _zod.z.array(_zod.z.string()).optional().describe("Optional list of suggested response options")
10
+ }),
11
+ execute: async ({ question, options }) => {
12
+ if (!config.onQuestion) {
13
+ return "Error [ask-user]: No onQuestion callback configured. Provide an onQuestion function in the tool config to enable user interaction.";
14
+ }
15
+ try {
16
+ const response = await config.onQuestion(question, options);
17
+ return response;
18
+ } catch (error) {
19
+ const msg = error instanceof Error ? error.message : String(error);
20
+ return `Error [ask-user]: Failed to get user response: ${msg}`;
21
+ }
22
+ }
23
+ });
24
+ }
25
+ var askUser = createAskUser();
26
+
27
+
28
+
29
+
30
+ exports.createAskUser = createAskUser; exports.askUser = askUser;
@@ -0,0 +1,79 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
2
+
3
+
4
+
5
+ var _chunk5NW4OGRIcjs = require('./chunk-5NW4OGRI.cjs');
6
+
7
+
8
+ var _chunkCAEVLIQBcjs = require('./chunk-CAEVLIQB.cjs');
9
+
10
+
11
+ var _chunkQZ5GS6HWcjs = require('./chunk-QZ5GS6HW.cjs');
12
+
13
+ // src/multi-edit/index.ts
14
+ var _promises = require('fs/promises');
15
+ var _ai = require('ai');
16
+ var _zod = require('zod');
17
+ function countOccurrences(text, search) {
18
+ if (search.length === 0) return 0;
19
+ let count = 0;
20
+ let pos = 0;
21
+ while ((pos = text.indexOf(search, pos)) !== -1) {
22
+ count++;
23
+ pos += search.length;
24
+ }
25
+ return count;
26
+ }
27
+ function createMultiEdit(config = {}) {
28
+ const cwd = _nullishCoalesce(config.cwd, () => ( process.cwd()));
29
+ return _ai.tool.call(void 0, {
30
+ description: "Atomically apply multiple text edits to a single file. All edits succeed together or none are applied (rollback on failure). Each edit replaces one occurrence of old_string with new_string. Edits are applied sequentially in the order provided.",
31
+ inputSchema: _zod.z.object({
32
+ file_path: _zod.z.string().describe("Path to the file to edit (absolute or relative to cwd)"),
33
+ edits: _zod.z.array(
34
+ _zod.z.object({
35
+ old_string: _zod.z.string().describe("The exact string to find and replace"),
36
+ new_string: _zod.z.string().describe("The replacement string")
37
+ })
38
+ ).describe("Ordered list of edits to apply atomically")
39
+ }),
40
+ execute: async ({ file_path, edits }) => {
41
+ try {
42
+ if (edits.length === 0) {
43
+ return "No edits provided. File unchanged.";
44
+ }
45
+ const resolvedPath = _chunkQZ5GS6HWcjs.expandPath.call(void 0, file_path, cwd);
46
+ const originalContent = await _promises.readFile.call(void 0, resolvedPath, "utf-8");
47
+ let content = originalContent;
48
+ for (let i = 0; i < edits.length; i++) {
49
+ const edit = edits[i];
50
+ const actualOldString = _chunk5NW4OGRIcjs.findActualString.call(void 0, content, edit.old_string);
51
+ if (actualOldString === null) {
52
+ return `Error [multi-edit]: Edit ${i + 1}/${edits.length} failed \u2014 old_string not found in file. No edits were applied. File: ${resolvedPath}`;
53
+ }
54
+ const occurrences = countOccurrences(content, actualOldString);
55
+ if (occurrences > 1) {
56
+ return `Error [multi-edit]: Edit ${i + 1}/${edits.length} failed \u2014 old_string matches ${occurrences} locations (must be unique). No edits were applied. File: ${resolvedPath}`;
57
+ }
58
+ const styledNewString = _chunk5NW4OGRIcjs.preserveQuoteStyle.call(void 0,
59
+ edit.old_string,
60
+ actualOldString,
61
+ edit.new_string
62
+ );
63
+ content = _chunk5NW4OGRIcjs.applyEditToFile.call(void 0, content, actualOldString, styledNewString);
64
+ }
65
+ await _chunkCAEVLIQBcjs.writeTextContent.call(void 0, resolvedPath, content);
66
+ return `Successfully applied ${edits.length} edit${edits.length === 1 ? "" : "s"} to ${resolvedPath}`;
67
+ } catch (error) {
68
+ const msg = error instanceof Error ? error.message : String(error);
69
+ return `Error [multi-edit]: ${msg}`;
70
+ }
71
+ }
72
+ });
73
+ }
74
+ var multiEdit = createMultiEdit();
75
+
76
+
77
+
78
+
79
+ exports.createMultiEdit = createMultiEdit; exports.multiEdit = multiEdit;
@@ -0,0 +1,142 @@
1
+ // src/bash/index.ts
2
+ import { tool } from "ai";
3
+ import { z } from "zod";
4
+
5
+ // src/shared/shell.ts
6
+ import { spawn } from "child_process";
7
+ var MAX_BUFFER_BYTES = 10 * 1024 * 1024;
8
+ var DEFAULT_TIMEOUT_MS = 12e4;
9
+ var SIGKILL_GRACE_MS = 5e3;
10
+ async function executeShell(command, options) {
11
+ const shellBin = options?.shell ?? process.env.SHELL ?? "/bin/bash";
12
+ const timeout = options?.timeout ?? DEFAULT_TIMEOUT_MS;
13
+ return new Promise((resolve, reject) => {
14
+ const child = spawn(shellBin, ["-c", command], {
15
+ cwd: options?.cwd,
16
+ stdio: ["pipe", "pipe", "pipe"],
17
+ // Prevent visible console window on Windows (no-op elsewhere)
18
+ windowsHide: true
19
+ });
20
+ let stdout = "";
21
+ let stderr = "";
22
+ let stdoutBytes = 0;
23
+ let stderrBytes = 0;
24
+ let settled = false;
25
+ let timeoutId;
26
+ let graceId;
27
+ function cleanup() {
28
+ if (timeoutId !== void 0) {
29
+ clearTimeout(timeoutId);
30
+ timeoutId = void 0;
31
+ }
32
+ if (graceId !== void 0) {
33
+ clearTimeout(graceId);
34
+ graceId = void 0;
35
+ }
36
+ if (abortHandler && options?.signal) {
37
+ options.signal.removeEventListener("abort", abortHandler);
38
+ }
39
+ }
40
+ function settle(result) {
41
+ if (settled) return;
42
+ settled = true;
43
+ cleanup();
44
+ resolve(result);
45
+ }
46
+ child.stdout.on("data", (chunk) => {
47
+ if (stdoutBytes >= MAX_BUFFER_BYTES) return;
48
+ const str = chunk.toString();
49
+ const remaining = MAX_BUFFER_BYTES - stdoutBytes;
50
+ if (chunk.length > remaining) {
51
+ stdout += str.slice(0, remaining);
52
+ stdoutBytes = MAX_BUFFER_BYTES;
53
+ } else {
54
+ stdout += str;
55
+ stdoutBytes += chunk.length;
56
+ }
57
+ });
58
+ child.stderr.on("data", (chunk) => {
59
+ if (stderrBytes >= MAX_BUFFER_BYTES) return;
60
+ const str = chunk.toString();
61
+ const remaining = MAX_BUFFER_BYTES - stderrBytes;
62
+ if (chunk.length > remaining) {
63
+ stderr += str.slice(0, remaining);
64
+ stderrBytes = MAX_BUFFER_BYTES;
65
+ } else {
66
+ stderr += str;
67
+ stderrBytes += chunk.length;
68
+ }
69
+ });
70
+ child.on("exit", (code, signal) => {
71
+ const exitCode = code !== null ? code : signal === "SIGKILL" ? 137 : signal === "SIGTERM" ? 143 : 1;
72
+ settle({ stdout, stderr, exitCode });
73
+ });
74
+ child.on("error", (err) => {
75
+ if (settled) return;
76
+ settled = true;
77
+ cleanup();
78
+ reject(err);
79
+ });
80
+ if (timeout > 0) {
81
+ timeoutId = setTimeout(() => {
82
+ timeoutId = void 0;
83
+ if (settled) return;
84
+ child.kill("SIGTERM");
85
+ graceId = setTimeout(() => {
86
+ graceId = void 0;
87
+ if (settled) return;
88
+ child.kill("SIGKILL");
89
+ }, SIGKILL_GRACE_MS);
90
+ }, timeout);
91
+ }
92
+ const abortHandler = options?.signal ? () => {
93
+ if (settled) return;
94
+ child.kill("SIGTERM");
95
+ } : void 0;
96
+ if (abortHandler && options?.signal) {
97
+ if (options.signal.aborted) {
98
+ child.kill("SIGTERM");
99
+ } else {
100
+ options.signal.addEventListener("abort", abortHandler, { once: true });
101
+ }
102
+ }
103
+ });
104
+ }
105
+
106
+ // src/bash/index.ts
107
+ function createBash(config = {}) {
108
+ const cwd = config.cwd ?? process.cwd();
109
+ const timeout = config.timeout ?? 12e4;
110
+ return tool({
111
+ description: "Execute a shell command and return its output. Runs the command in a bash shell with the configured working directory. Returns stdout, stderr, and exit code. Use this for running build commands, git operations, system administration, and any other shell tasks.",
112
+ inputSchema: z.object({
113
+ command: z.string().describe("The shell command to execute"),
114
+ timeout: z.number().optional().describe("Timeout in milliseconds (default: 120000)"),
115
+ description: z.string().optional().describe("Human-readable description of what the command does")
116
+ }),
117
+ execute: async ({ command, timeout: cmdTimeout }) => {
118
+ try {
119
+ const result = await executeShell(command, {
120
+ cwd,
121
+ timeout: cmdTimeout ?? timeout,
122
+ shell: config.shell
123
+ });
124
+ const parts = [];
125
+ if (result.stdout) parts.push(result.stdout);
126
+ if (result.stderr) parts.push(`STDERR:
127
+ ${result.stderr}`);
128
+ if (result.exitCode !== 0) parts.push(`Exit code: ${result.exitCode}`);
129
+ return parts.length > 0 ? parts.join("\n") : `Command completed with exit code ${result.exitCode}`;
130
+ } catch (error) {
131
+ const msg = error instanceof Error ? error.message : String(error);
132
+ return `Error [bash]: Failed to execute command: ${msg}`;
133
+ }
134
+ }
135
+ });
136
+ }
137
+ var bash = createBash();
138
+
139
+ export {
140
+ createBash,
141
+ bash
142
+ };
@@ -0,0 +1,99 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/shared/edit-helpers.ts
2
+ var LEFT_SINGLE_CURLY_QUOTE = "\u2018";
3
+ var RIGHT_SINGLE_CURLY_QUOTE = "\u2019";
4
+ var LEFT_DOUBLE_CURLY_QUOTE = "\u201C";
5
+ var RIGHT_DOUBLE_CURLY_QUOTE = "\u201D";
6
+ function normalizeQuotes(str) {
7
+ return str.replaceAll(LEFT_SINGLE_CURLY_QUOTE, "'").replaceAll(RIGHT_SINGLE_CURLY_QUOTE, "'").replaceAll(LEFT_DOUBLE_CURLY_QUOTE, '"').replaceAll(RIGHT_DOUBLE_CURLY_QUOTE, '"');
8
+ }
9
+ function findActualString(fileContent, searchString) {
10
+ if (fileContent.includes(searchString)) {
11
+ return searchString;
12
+ }
13
+ const normalizedSearch = normalizeQuotes(searchString);
14
+ const normalizedFile = normalizeQuotes(fileContent);
15
+ const searchIndex = normalizedFile.indexOf(normalizedSearch);
16
+ if (searchIndex !== -1) {
17
+ return fileContent.substring(
18
+ searchIndex,
19
+ searchIndex + searchString.length
20
+ );
21
+ }
22
+ return null;
23
+ }
24
+ function preserveQuoteStyle(oldString, actualOldString, newString) {
25
+ if (oldString === actualOldString) {
26
+ return newString;
27
+ }
28
+ const hasDoubleQuotes = actualOldString.includes(LEFT_DOUBLE_CURLY_QUOTE) || actualOldString.includes(RIGHT_DOUBLE_CURLY_QUOTE);
29
+ const hasSingleQuotes = actualOldString.includes(LEFT_SINGLE_CURLY_QUOTE) || actualOldString.includes(RIGHT_SINGLE_CURLY_QUOTE);
30
+ if (!hasDoubleQuotes && !hasSingleQuotes) {
31
+ return newString;
32
+ }
33
+ let result = newString;
34
+ if (hasDoubleQuotes) {
35
+ result = applyCurlyDoubleQuotes(result);
36
+ }
37
+ if (hasSingleQuotes) {
38
+ result = applyCurlySingleQuotes(result);
39
+ }
40
+ return result;
41
+ }
42
+ function applyEditToFile(originalContent, oldString, newString, replaceAll = false) {
43
+ const f = replaceAll ? (content, search, replace) => content.replaceAll(search, () => replace) : (content, search, replace) => content.replace(search, () => replace);
44
+ if (newString !== "") {
45
+ return f(originalContent, oldString, newString);
46
+ }
47
+ const stripTrailingNewline = !oldString.endsWith("\n") && originalContent.includes(oldString + "\n");
48
+ return stripTrailingNewline ? f(originalContent, oldString + "\n", newString) : f(originalContent, oldString, newString);
49
+ }
50
+ function isOpeningContext(chars, index) {
51
+ if (index === 0) {
52
+ return true;
53
+ }
54
+ const prev = chars[index - 1];
55
+ return prev === " " || prev === " " || prev === "\n" || prev === "\r" || prev === "(" || prev === "[" || prev === "{" || prev === "\u2014" || // em dash
56
+ prev === "\u2013";
57
+ }
58
+ function applyCurlyDoubleQuotes(str) {
59
+ const chars = [...str];
60
+ const result = [];
61
+ for (let i = 0; i < chars.length; i++) {
62
+ if (chars[i] === '"') {
63
+ result.push(
64
+ isOpeningContext(chars, i) ? LEFT_DOUBLE_CURLY_QUOTE : RIGHT_DOUBLE_CURLY_QUOTE
65
+ );
66
+ } else {
67
+ result.push(chars[i]);
68
+ }
69
+ }
70
+ return result.join("");
71
+ }
72
+ function applyCurlySingleQuotes(str) {
73
+ const chars = [...str];
74
+ const result = [];
75
+ for (let i = 0; i < chars.length; i++) {
76
+ if (chars[i] === "'") {
77
+ const prev = i > 0 ? chars[i - 1] : void 0;
78
+ const next = i < chars.length - 1 ? chars[i + 1] : void 0;
79
+ const prevIsLetter = prev !== void 0 && new RegExp("\\p{L}", "u").test(prev);
80
+ const nextIsLetter = next !== void 0 && new RegExp("\\p{L}", "u").test(next);
81
+ if (prevIsLetter && nextIsLetter) {
82
+ result.push(RIGHT_SINGLE_CURLY_QUOTE);
83
+ } else {
84
+ result.push(
85
+ isOpeningContext(chars, i) ? LEFT_SINGLE_CURLY_QUOTE : RIGHT_SINGLE_CURLY_QUOTE
86
+ );
87
+ }
88
+ } else {
89
+ result.push(chars[i]);
90
+ }
91
+ }
92
+ return result.join("");
93
+ }
94
+
95
+
96
+
97
+
98
+
99
+ exports.findActualString = findActualString; exports.preserveQuoteStyle = preserveQuoteStyle; exports.applyEditToFile = applyEditToFile;