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.
- package/README.md +627 -52
- package/dist/ask-user/index.cjs +8 -0
- package/dist/ask-user/index.d.cts +68 -0
- package/dist/ask-user/index.d.ts +68 -0
- package/dist/ask-user/index.js +8 -0
- package/dist/bash/index.cjs +8 -0
- package/dist/bash/index.d.cts +63 -0
- package/dist/bash/index.d.ts +63 -0
- package/dist/bash/index.js +8 -0
- package/dist/chunk-3EPGFWZV.cjs +30 -0
- package/dist/chunk-3VO6NETR.cjs +79 -0
- package/dist/chunk-4YI2H55A.js +142 -0
- package/dist/chunk-5NW4OGRI.cjs +99 -0
- package/dist/chunk-6MDPYALY.js +196 -0
- package/dist/chunk-6PQLFDGT.js +117 -0
- package/dist/chunk-7QL4BQCH.js +40 -0
- package/dist/chunk-CAEVLIQB.cjs +117 -0
- package/dist/chunk-CGTPF6IS.js +90 -0
- package/dist/chunk-EA3YV7ZG.js +79 -0
- package/dist/chunk-FAEGCFTO.js +136 -0
- package/dist/chunk-FV2R5FFQ.cjs +102 -0
- package/dist/chunk-FW3UJ622.cjs +59 -0
- package/dist/chunk-G3ITTPGX.js +99 -0
- package/dist/chunk-HDKXSKMO.js +30 -0
- package/dist/chunk-HZAQRHBT.js +99 -0
- package/dist/chunk-I3ONDY7P.js +46 -0
- package/dist/chunk-I6KFFQPV.cjs +58 -0
- package/dist/chunk-IMZQ7ELK.cjs +196 -0
- package/dist/chunk-JCTBB7H2.cjs +40 -0
- package/dist/chunk-K77GC2QI.js +59 -0
- package/dist/chunk-LPV5CN2K.js +58 -0
- package/dist/chunk-MF7CJVIZ.js +40 -0
- package/dist/chunk-MIYA7TNR.cjs +123 -0
- package/dist/chunk-MJCAXASI.js +123 -0
- package/dist/chunk-MXFW3XY6.cjs +73 -0
- package/dist/chunk-ONBH74ZV.cjs +90 -0
- package/dist/chunk-OXLQ7QVL.cjs +40 -0
- package/dist/chunk-QEJV2KZ4.cjs +159 -0
- package/dist/chunk-QZ5GS6HW.cjs +46 -0
- package/dist/chunk-S6QEY7UY.js +73 -0
- package/dist/chunk-SUSAPI5W.cjs +142 -0
- package/dist/chunk-TBVHHF3H.cjs +47 -0
- package/dist/chunk-U2YMJM25.cjs +115 -0
- package/dist/chunk-VLNDEVKS.js +102 -0
- package/dist/chunk-XKG2A3EW.js +159 -0
- package/dist/chunk-XLD2Y3SS.cjs +136 -0
- package/dist/chunk-Y7KOKDFP.js +115 -0
- package/dist/chunk-YPPPGGLA.cjs +99 -0
- package/dist/chunk-ZHCMEQJJ.js +47 -0
- package/dist/context-compaction/index.cjs +8 -0
- package/dist/context-compaction/index.d.cts +77 -0
- package/dist/context-compaction/index.d.ts +77 -0
- package/dist/context-compaction/index.js +8 -0
- package/dist/diff/index.cjs +9 -0
- package/dist/diff/index.d.cts +72 -0
- package/dist/diff/index.d.ts +72 -0
- package/dist/diff/index.js +9 -0
- package/dist/edit/index.cjs +10 -0
- package/dist/edit/index.d.cts +53 -0
- package/dist/edit/index.d.ts +53 -0
- package/dist/edit/index.js +10 -0
- package/dist/glob/index.cjs +10 -0
- package/dist/glob/index.d.cts +47 -0
- package/dist/glob/index.d.ts +47 -0
- package/dist/glob/index.js +10 -0
- package/dist/grep/index.cjs +10 -0
- package/dist/grep/index.d.cts +50 -0
- package/dist/grep/index.d.ts +50 -0
- package/dist/grep/index.js +10 -0
- package/dist/http-request/index.cjs +8 -0
- package/dist/http-request/index.d.cts +60 -0
- package/dist/http-request/index.d.ts +60 -0
- package/dist/http-request/index.js +8 -0
- package/dist/index.cjs +102 -0
- package/dist/index.d.cts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +102 -0
- package/dist/lsp/index.cjs +10 -0
- package/dist/lsp/index.d.cts +38 -0
- package/dist/lsp/index.d.ts +38 -0
- package/dist/lsp/index.js +10 -0
- package/dist/memory/index.cjs +9 -0
- package/dist/memory/index.d.cts +63 -0
- package/dist/memory/index.d.ts +63 -0
- package/dist/memory/index.js +9 -0
- package/dist/multi-edit/index.cjs +11 -0
- package/dist/multi-edit/index.d.cts +72 -0
- package/dist/multi-edit/index.d.ts +72 -0
- package/dist/multi-edit/index.js +11 -0
- package/dist/read/index.cjs +10 -0
- package/dist/read/index.d.cts +67 -0
- package/dist/read/index.d.ts +67 -0
- package/dist/read/index.js +10 -0
- package/dist/sleep/index.cjs +8 -0
- package/dist/sleep/index.d.cts +60 -0
- package/dist/sleep/index.d.ts +60 -0
- package/dist/sleep/index.js +8 -0
- package/dist/task/index.cjs +8 -0
- package/dist/task/index.d.cts +67 -0
- package/dist/task/index.d.ts +67 -0
- package/dist/task/index.js +8 -0
- package/dist/types-3QPDuCXN.d.cts +45 -0
- package/dist/types-3QPDuCXN.d.ts +45 -0
- package/dist/web-fetch/index.cjs +8 -0
- package/dist/web-fetch/index.d.cts +56 -0
- package/dist/web-fetch/index.d.ts +56 -0
- package/dist/web-fetch/index.js +8 -0
- package/dist/write/index.cjs +10 -0
- package/dist/write/index.d.cts +47 -0
- package/dist/write/index.d.ts +47 -0
- package/dist/write/index.js +10 -0
- package/package.json +145 -20
- package/dist/core/index.d.ts +0 -20
- package/dist/core/index.js +0 -1
- package/dist/core/index.js.map +0 -1
|
@@ -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,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,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;
|