@acontext/acontext 0.1.1 → 0.1.3

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.
@@ -3,4 +3,4 @@
3
3
  */
4
4
  export declare const SKILL_REMINDER = "MANDATORY SKILL READING AND EXECUTION PROTOCOL:\nBEFORE writing ANY code or using ANY execution tools, You MUST complete ALL of\nthese steps:\n\nSTEP 1 - IDENTIFY ALL RELEVANT SKILLS:\n- Scan the user message for ALL trigger words from ALL skills\n- Identify EVERY skill that matches ANY trigger word\n- If multiple skills match, ALL must be processed\n- If no skills match, you can skip the following steps\n\nSTEP 2 - READ ALL SKILL FILES:\n- Use the text_editor_sandbox tool to view EACH identified skill's SKILL.md file\n- READ COMPLETELY - do not skim or skip sections\n- This step is MANDATORY even if multiple skills are involved\n- DO NOT proceed until ALL relevant skill files have been read\n\nSTEP 3 - EXECUTE ALL SKILL INSTRUCTIONS:\n- Follow the EXACT instructions from EACH skill file read\n- If a skill file says to execute file X, then EXECUTE file X\n- If a skill file provides code patterns, USE those patterns\n- Apply instructions from ALL skills, not just the first one\n- NEVER write generic code when skill-specific code exists\n\nCRITICAL RULES:\n- Reading the skill file is NOT sufficient - you must FOLLOW its instructions\n- Multiple skills = multiple skill files to read AND follow\n- Each skill's instructions must be executed, not just acknowledged\n- NEVER skip a skill because you already read another skill\n- The skills contain specialized, tested code that MUST be used\n\nDO NOT SKIP ANY SKILL FILES OR THEIR INSTRUCTIONS. This protocol applies to EVERY\nskill that matches the user's request, without exception.";
5
5
  export declare const SANDBOX_TEXT_EDITOR_REMINDER = "The text_editor_sandbox tool enables viewing, creating, and modifying text files within\nthe secure sandboxed container environment.\n\nHow it works:\n- All file operations occur within the sandboxed container filesystem\n\nCommand guidelines:\n- Always use view before editing to understand file structure\n- For str_replace commands, ensure search strings are unique and exact\n- Include sufficient context in str_replace for accurate placement\n- Use proper escaping for special characters in search/replace strings";
6
- export declare const SANDBOX_BASH_REMINDER = "When to use the bash_execution_sandbox tool directly:\n- File system operations requiring shell commands (moving, copying, renaming, organizing files)\n- Text processing and manipulation using standard Unix tools (grep, sed, awk, cut, sort, etc.) that\nshould not be done by the text editor tool\n- Batch processing of multiple files using shell loops and wildcards\n- System inspection tasks (checking file sizes, permissions, directory structures)\n- Combining multiple command-line tools in pipelines for complex data processing\n- Archive operations (tar, unzip) and file compression/decompression\n- Converting between file formats using command-line utilities\n\nWhen you should write Python file and use bash tool to run it:\n- Complex data analysis or numerical computation (use file operations to write a Python script instead, and\nthen the bash to run the script)\n- Tasks requiring advanced programming logic or data structures\n\nWhen NOT to use the bash_execution_sandbox tool:\n- Simple questions that can be answered without executing commands\n- Tasks that only require explaining shell concepts without actual execution\n\nHow it works:\n- Scripts are saved to a temporary sandbox and executed with bash\n- Tool results will include stdout, stderr, and return code\n- User-uploaded files are accessible in the directory specified by the INPUT_DIR environment variable. If\nyou know the file path and don't need to open the full INPUT_DIR, then just open the file directly\n\nFile Operations (CRITICAL - READ CAREFULLY):\n- use text_editor_sandbox tool to view, create, and edit files.\n\nExport Your Result:\n- All the files you created kept in the sandbox, which user can't see or access.\n- If you want to export them to user, use `export_file_sandbox` tool.\n- If too many files to export(>= 6 files), zip those files and export the zip file.\n- Result files' names should be unique and descriptive, (wrong: result.md, output.md... right: 2026_us_market_trending.png)\n\nScript guidelines:\n- Write POSIX-compliant bash scripts\n- Use proper error handling and exit codes\n- Quote variables appropriately to handle spaces in filenames\n- Keep scripts clean and well-organized\n- For file operations, use text_editor_sandbox tool instead of bash commands.\n\nNever write blocking script:\n- python codes like `plt.show()` or `input()`... will block the execution of the script, don't use them. write non-blocking code instead.\n\nContainer environment:\n- Filesystem persists across multiple executions within the same container\n- Standard Unix utilities available (grep, sed, awk, etc.)\n- Archive tools: tar, unzip, zip\n- Additional tools: ripgrep, fd, sqlite3, jq, imagemagick\n- Do not try to install new packages and libraries with pip as there is no internet access\n";
6
+ export declare const SANDBOX_BASH_REMINDER = "When to use the bash_execution_sandbox tool directly:\n- File system operations requiring shell commands (moving, copying, renaming, organizing files)\n- Text processing and manipulation using standard Unix tools (grep, sed, awk, cut, sort, etc.) that\nshould not be done by the text editor tool\n- Batch processing of multiple files using shell loops and wildcards\n- System inspection tasks (checking file sizes, permissions, directory structures)\n- Combining multiple command-line tools in pipelines for complex data processing\n- Archive operations (tar, unzip) and file compression/decompression\n- Converting between file formats using command-line utilities\n\nWhen you should write Python file and use bash tool to run it:\n- Complex data analysis or numerical computation (use file operations to write a Python script instead, and\nthen the bash to run the script)\n- Tasks requiring advanced programming logic or data structures\n\nWhen NOT to use the bash_execution_sandbox tool:\n- Simple questions that can be answered without executing commands\n- Tasks that only require explaining shell concepts without actual execution\n\nHow it works:\n- Scripts are saved to a temporary sandbox and executed with bash\n- Tool results will include stdout, stderr, and return code\n- User-uploaded files are accessible in the directory specified by the INPUT_DIR environment variable. If\nyou know the file path and don't need to open the full INPUT_DIR, then just open the file directly\n\nFile Operations (CRITICAL - READ CAREFULLY):\n- use text_editor_sandbox tool to view, create, and edit files.\n\nExport Your Result:\n- All the files you created kept in the sandbox, which user can't see or access.\n- If you want to export them to user, use `export_file_sandbox` tool.\n- If too many files to export(>= 6 files), zip those files and export the zip file.\n- Result files' names should be unique and descriptive, (wrong: result.md, output.md... right: 2026_us_market_trending.png)\n\nScript guidelines:\n- Write POSIX-compliant bash scripts\n- Use proper error handling and exit codes\n- Quote variables appropriately to handle spaces in filenames\n- Keep scripts clean and well-organized\n- For file operations, use text_editor_sandbox tool instead of bash commands.\n\nNever write blocking script:\n- python codes like `plt.show()` or `input()`... will block the execution of the script, don't use them. write non-blocking code instead.\n\nContainer environment:\n- Filesystem persists across multiple executions within the same container\n- Standard Unix utilities available (grep, sed, awk, etc.)\n- Archive tools: tar, unzip, zip\n- Additional tools: ripgrep, fd, sqlite3, jq, imagemagick\n- You can install new packages with pip if needed (internet access is available)\n\nRemember to always export your artifacts at the end of your task so that the user can view them.\n";
@@ -96,5 +96,7 @@ Container environment:
96
96
  - Standard Unix utilities available (grep, sed, awk, etc.)
97
97
  - Archive tools: tar, unzip, zip
98
98
  - Additional tools: ripgrep, fd, sqlite3, jq, imagemagick
99
- - Do not try to install new packages and libraries with pip as there is no internet access
99
+ - You can install new packages with pip if needed (internet access is available)
100
+
101
+ Remember to always export your artifacts at the end of your task so that the user can view them.
100
102
  `;
@@ -64,6 +64,9 @@ export declare class TextEditorTool extends AbstractBaseTool {
64
64
  };
65
65
  view_range: {
66
66
  type: string[];
67
+ items: {
68
+ type: string;
69
+ };
67
70
  description: string;
68
71
  };
69
72
  };
@@ -41,6 +41,13 @@ const path = __importStar(require("path"));
41
41
  const base_1 = require("./base");
42
42
  const prompts_1 = require("./prompts");
43
43
  const text_editor_1 = require("./text-editor");
44
+ const MAX_OUTPUT_CHARS = 20000;
45
+ function truncateOutput(text, maxChars = MAX_OUTPUT_CHARS) {
46
+ if (text.length > maxChars) {
47
+ return text.slice(0, maxChars) + '...[truncated]';
48
+ }
49
+ return text;
50
+ }
44
51
  function formatMountedSkills(mountedSkillPaths) {
45
52
  if (mountedSkillPaths.size === 0) {
46
53
  return '';
@@ -120,8 +127,8 @@ class BashTool extends base_1.AbstractBaseTool {
120
127
  timeout,
121
128
  });
122
129
  return JSON.stringify({
123
- stdout: result.stdout,
124
- stderr: result.stderr,
130
+ stdout: truncateOutput(result.stdout),
131
+ stderr: truncateOutput(result.stderr),
125
132
  exit_code: result.exit_code,
126
133
  });
127
134
  }
@@ -136,27 +143,32 @@ class TextEditorTool extends base_1.AbstractBaseTool {
136
143
  command: {
137
144
  type: 'string',
138
145
  enum: ['view', 'create', 'str_replace'],
139
- description: "The operation to perform: 'view', 'create', or 'str_replace'",
146
+ description: "The operation to perform: 'view', 'create', or 'str_replace'. " +
147
+ "Required parameters per command: " +
148
+ "'view' requires path (view_range is optional); " +
149
+ "'create' requires path and file_text; " +
150
+ "'str_replace' requires path, old_str, and new_str.",
140
151
  },
141
152
  path: {
142
153
  type: 'string',
143
- description: "The file path in the sandbox (e.g., '/workspace/script.py')",
154
+ description: "Required for all commands. The file path in the sandbox (e.g., '/workspace/script.py')",
144
155
  },
145
156
  file_text: {
146
157
  type: ['string', 'null'],
147
- description: "For 'create' command: the content to write to the file",
158
+ description: "Required for 'create' command. The content to write to the file.",
148
159
  },
149
160
  old_str: {
150
161
  type: ['string', 'null'],
151
- description: "For 'str_replace' command: the exact string to find and replace",
162
+ description: "Required for 'str_replace' command. The exact string to find and replace.",
152
163
  },
153
164
  new_str: {
154
165
  type: ['string', 'null'],
155
- description: "For 'str_replace' command: the string to replace old_str with",
166
+ description: "Required for 'str_replace' command. The string to replace old_str with.",
156
167
  },
157
168
  view_range: {
158
169
  type: ['array', 'null'],
159
- description: "For 'view' command: optional [start_line, end_line] to view specific lines",
170
+ items: { type: 'integer' },
171
+ description: "Optional for 'view' command. An array [start_line, end_line] to view specific lines. If not provided, shows the first 200 lines.",
160
172
  },
161
173
  };
162
174
  this.requiredArguments = ['command', 'path'];
@@ -22,23 +22,22 @@ export interface CreateFileResult {
22
22
  stderr?: string;
23
23
  }
24
24
  export interface StrReplaceResult {
25
- oldStart?: number;
26
- oldLines?: number;
27
- newStart?: number;
28
- newLines?: number;
29
- lines?: string[];
25
+ msg?: string;
30
26
  error?: string;
31
27
  stderr?: string;
32
28
  }
33
29
  /**
34
30
  * View file content with line numbers.
35
31
  */
36
- export declare function viewFile(ctx: SandboxContext, path: string, viewRange: number[] | null, timeout?: number): Promise<ViewFileResult>;
32
+ export declare function viewFile(ctx: SandboxContext, filePath: string, viewRange: number[] | null, timeout?: number): Promise<ViewFileResult>;
37
33
  /**
38
34
  * Create a new file with content.
39
35
  */
40
- export declare function createFile(ctx: SandboxContext, path: string, fileText: string, timeout?: number): Promise<CreateFileResult>;
36
+ export declare function createFile(ctx: SandboxContext, filePath: string, fileText: string, timeout?: number): Promise<CreateFileResult>;
41
37
  /**
42
38
  * Replace a string in a file.
39
+ *
40
+ * Uses a Python script on the sandbox to avoid transferring the entire file.
41
+ * Only the base64-encoded oldStr and newStr are sent.
43
42
  */
44
- export declare function strReplace(ctx: SandboxContext, path: string, oldStr: string, newStr: string, timeout?: number): Promise<StrReplaceResult>;
43
+ export declare function strReplace(ctx: SandboxContext, filePath: string, oldStr: string, newStr: string, timeout?: number): Promise<StrReplaceResult>;
@@ -2,11 +2,25 @@
2
2
  /**
3
3
  * Text editor file operations for sandbox environments.
4
4
  */
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
5
8
  Object.defineProperty(exports, "__esModule", { value: true });
6
9
  exports.escapeForShell = escapeForShell;
7
10
  exports.viewFile = viewFile;
8
11
  exports.createFile = createFile;
9
12
  exports.strReplace = strReplace;
13
+ const path_1 = __importDefault(require("path"));
14
+ const MAX_CONTENT_CHARS = 20000;
15
+ /**
16
+ * Truncate text to maxChars, appending a truncation flag if needed.
17
+ */
18
+ function truncateContent(text, maxChars = MAX_CONTENT_CHARS) {
19
+ if (text.length > maxChars) {
20
+ return text.slice(0, maxChars) + '...[truncated]';
21
+ }
22
+ return text;
23
+ }
10
24
  /**
11
25
  * Escape a string for safe use in shell commands.
12
26
  */
@@ -17,54 +31,48 @@ function escapeForShell(s) {
17
31
  /**
18
32
  * View file content with line numbers.
19
33
  */
20
- async function viewFile(ctx, path, viewRange, timeout) {
21
- // First check if file exists and get total lines
22
- const checkCmd = `wc -l < ${escapeForShell(path)} 2>/dev/null || echo 'FILE_NOT_FOUND'`;
23
- const checkResult = await ctx.client.sandboxes.execCommand({
24
- sandboxId: ctx.sandboxId,
25
- command: checkCmd,
26
- timeout,
27
- });
28
- if (checkResult.stdout.includes('FILE_NOT_FOUND') || checkResult.exit_code !== 0) {
29
- return {
30
- error: `File not found: ${path}`,
31
- stderr: checkResult.stderr,
32
- };
33
- }
34
- const totalLines = /^\d+$/.test(checkResult.stdout.trim())
35
- ? parseInt(checkResult.stdout.trim(), 10)
36
- : 0;
37
- // Build the view command with line numbers
38
- let cmd;
34
+ async function viewFile(ctx, filePath, viewRange, timeout) {
35
+ const escapedPath = escapeForShell(filePath);
36
+ // Build combined command: check existence, get total lines, and view content in one exec
37
+ let viewCmd;
39
38
  let startLine;
40
39
  if (viewRange && viewRange.length === 2) {
41
40
  const [rangeStart, rangeEnd] = viewRange;
42
- cmd = `sed -n '${rangeStart},${rangeEnd}p' ${escapeForShell(path)} | nl -ba -v ${rangeStart}`;
41
+ viewCmd = `sed -n '${rangeStart},${rangeEnd}p' ${escapedPath} | nl -ba -v ${rangeStart}`;
43
42
  startLine = rangeStart;
44
43
  }
45
44
  else {
46
- cmd = `nl -ba ${escapeForShell(path)}`;
45
+ const maxLines = 200;
46
+ viewCmd = `head -n ${maxLines} ${escapedPath} | nl -ba`;
47
47
  startLine = 1;
48
48
  }
49
+ // Single combined command: outputs "TOTAL:<n>" on first line, then file content
50
+ const cmd = `if [ ! -f ${escapedPath} ]; then echo 'FILE_NOT_FOUND'; exit 1; fi; echo "TOTAL:$(wc -l < ${escapedPath})"; ${viewCmd}`;
49
51
  const result = await ctx.client.sandboxes.execCommand({
50
52
  sandboxId: ctx.sandboxId,
51
53
  command: cmd,
52
54
  timeout,
53
55
  });
54
- if (result.exit_code !== 0) {
56
+ if (result.exit_code !== 0 || result.stdout.includes('FILE_NOT_FOUND')) {
55
57
  return {
56
- error: `Failed to view file: ${path}`,
58
+ error: `File not found: ${filePath}`,
57
59
  stderr: result.stderr,
58
60
  };
59
61
  }
60
- // Count lines in output
61
- const contentLines = result.stdout.trim()
62
- ? result.stdout.trimEnd().split('\n')
63
- : [];
62
+ // Parse output: first line is "TOTAL:<n>", rest is content
63
+ const lines = result.stdout.split('\n');
64
+ let totalLines = 0;
65
+ let content = '';
66
+ if (lines.length > 0 && lines[0].startsWith('TOTAL:')) {
67
+ const totalStr = lines[0].substring(6).trim();
68
+ totalLines = /^\d+$/.test(totalStr) ? parseInt(totalStr, 10) : 0;
69
+ content = lines.slice(1).join('\n');
70
+ }
71
+ const contentLines = content.trim() ? content.trimEnd().split('\n') : [];
64
72
  const numLines = contentLines.length;
65
73
  return {
66
74
  file_type: 'text',
67
- content: result.stdout,
75
+ content: truncateContent(content),
68
76
  numLines,
69
77
  startLine: viewRange ? startLine : 1,
70
78
  totalLines: totalLines + 1, // wc -l doesn't count last line without newline
@@ -73,129 +81,83 @@ async function viewFile(ctx, path, viewRange, timeout) {
73
81
  /**
74
82
  * Create a new file with content.
75
83
  */
76
- async function createFile(ctx, path, fileText, timeout) {
77
- // Check if file already exists
78
- const checkCmd = `test -f ${escapeForShell(path)} && echo 'EXISTS' || echo 'NEW'`;
79
- const checkResult = await ctx.client.sandboxes.execCommand({
80
- sandboxId: ctx.sandboxId,
81
- command: checkCmd,
82
- timeout,
83
- });
84
- const isUpdate = checkResult.stdout.includes('EXISTS');
85
- // Create directory if needed
86
- const parts = path.split('/');
87
- parts.pop();
88
- const dirPath = parts.join('/');
89
- if (dirPath) {
90
- const mkdirCmd = `mkdir -p ${escapeForShell(dirPath)}`;
91
- await ctx.client.sandboxes.execCommand({
92
- sandboxId: ctx.sandboxId,
93
- command: mkdirCmd,
94
- timeout,
95
- });
96
- }
97
- // Write file using base64 encoding to safely transfer content
84
+ async function createFile(ctx, filePath, fileText, timeout) {
85
+ const escapedPath = escapeForShell(filePath);
98
86
  const encodedContent = Buffer.from(fileText, 'utf-8').toString('base64');
99
- const writeCmd = `echo ${escapeForShell(encodedContent)} | base64 -d > ${escapeForShell(path)}`;
87
+ // Get directory path for mkdir
88
+ const dirPath = path_1.default.posix.dirname(filePath);
89
+ const mkdirPart = dirPath && dirPath !== '.' ? `mkdir -p ${escapeForShell(dirPath)} && ` : '';
90
+ // Single combined command: check existence, create dir, write file
91
+ const cmd = `is_update=$(test -f ${escapedPath} && echo 1 || echo 0); ${mkdirPart}echo ${escapeForShell(encodedContent)} | base64 -d > ${escapedPath} && echo "STATUS:$is_update"`;
100
92
  const result = await ctx.client.sandboxes.execCommand({
101
93
  sandboxId: ctx.sandboxId,
102
- command: writeCmd,
94
+ command: cmd,
103
95
  timeout,
104
96
  });
105
- if (result.exit_code !== 0) {
97
+ if (result.exit_code !== 0 || !result.stdout.includes('STATUS:')) {
106
98
  return {
107
- error: `Failed to create file: ${path}`,
99
+ error: `Failed to create file: ${filePath}`,
108
100
  stderr: result.stderr,
109
101
  };
110
102
  }
103
+ const isUpdate = result.stdout.includes('STATUS:1');
111
104
  return {
112
105
  is_file_update: isUpdate,
113
- message: `File ${isUpdate ? 'updated' : 'created'}: ${path}`,
106
+ message: `File ${isUpdate ? 'updated' : 'created'}: ${filePath}`,
114
107
  };
115
108
  }
116
109
  /**
117
110
  * Replace a string in a file.
111
+ *
112
+ * Uses a Python script on the sandbox to avoid transferring the entire file.
113
+ * Only the base64-encoded oldStr and newStr are sent.
118
114
  */
119
- async function strReplace(ctx, path, oldStr, newStr, timeout) {
120
- // First read the file content
121
- const readCmd = `cat ${escapeForShell(path)}`;
115
+ async function strReplace(ctx, filePath, oldStr, newStr, timeout) {
116
+ const oldB64 = Buffer.from(oldStr, 'utf-8').toString('base64');
117
+ const newB64 = Buffer.from(newStr, 'utf-8').toString('base64');
118
+ // Write Python script and base64 encode it to avoid shell escaping issues
119
+ const pyScript = `import sys, base64, os
120
+ old = base64.b64decode("${oldB64}").decode()
121
+ new = base64.b64decode("${newB64}").decode()
122
+ path = "${filePath}"
123
+ if not os.path.exists(path):
124
+ print("FILE_NOT_FOUND")
125
+ sys.exit(1)
126
+ with open(path, "r") as f:
127
+ content = f.read()
128
+ count = content.count(old)
129
+ if count == 0:
130
+ print("NOT_FOUND")
131
+ sys.exit(0)
132
+ if count > 1:
133
+ print(f"MULTIPLE:{count}")
134
+ sys.exit(0)
135
+ with open(path, "w") as f:
136
+ f.write(content.replace(old, new, 1))
137
+ print("SUCCESS")
138
+ `;
139
+ const scriptB64 = Buffer.from(pyScript, 'utf-8').toString('base64');
140
+ const cmd = `echo ${escapeForShell(scriptB64)} | base64 -d | python3`;
122
141
  const result = await ctx.client.sandboxes.execCommand({
123
142
  sandboxId: ctx.sandboxId,
124
- command: readCmd,
143
+ command: cmd,
125
144
  timeout,
126
145
  });
127
- if (result.exit_code !== 0) {
128
- return {
129
- error: `File not found: ${path}`,
130
- stderr: result.stderr,
131
- };
132
- }
133
- const originalContent = result.stdout;
134
- // Check if oldStr exists in the file
135
- if (!originalContent.includes(oldStr)) {
136
- return {
137
- error: `String not found in file: ${oldStr.substring(0, 50)}...`,
138
- };
139
- }
140
- // Count occurrences
141
- let occurrences = 0;
142
- let searchIndex = 0;
143
- while (searchIndex < originalContent.length) {
144
- const foundIndex = originalContent.indexOf(oldStr, searchIndex);
145
- if (foundIndex === -1)
146
- break;
147
- occurrences++;
148
- searchIndex = foundIndex + oldStr.length;
149
- }
150
- if (occurrences > 1) {
151
- return {
152
- error: `Multiple occurrences (${occurrences}) of the string found. Please provide more context to make the match unique.`,
153
- };
146
+ const output = result.stdout.trim();
147
+ if (result.exit_code !== 0 || output === 'FILE_NOT_FOUND') {
148
+ return { error: `File not found: ${filePath}`, stderr: result.stderr };
154
149
  }
155
- // Perform the replacement
156
- const newContent = originalContent.replace(oldStr, newStr);
157
- // Find the line numbers affected
158
- const oldLines = originalContent.split('\n');
159
- const newLines = newContent.split('\n');
160
- // Find where the change starts
161
- let oldStart = 1;
162
- const minLen = Math.min(oldLines.length, newLines.length);
163
- for (let i = 0; i < minLen; i++) {
164
- if (oldLines[i] !== newLines[i]) {
165
- oldStart = i + 1;
166
- break;
167
- }
150
+ if (output === 'NOT_FOUND') {
151
+ return { error: `String not found in file: ${oldStr.substring(0, 50)}...` };
168
152
  }
169
- // Write the new content
170
- const encodedContent = Buffer.from(newContent, 'utf-8').toString('base64');
171
- const writeCmd = `echo ${escapeForShell(encodedContent)} | base64 -d > ${escapeForShell(path)}`;
172
- const writeResult = await ctx.client.sandboxes.execCommand({
173
- sandboxId: ctx.sandboxId,
174
- command: writeCmd,
175
- timeout,
176
- });
177
- if (writeResult.exit_code !== 0) {
153
+ if (output.startsWith('MULTIPLE:')) {
154
+ const count = output.split(':')[1];
178
155
  return {
179
- error: `Failed to write file: ${path}`,
180
- stderr: writeResult.stderr,
156
+ error: `Multiple occurrences (${count}) of the string found. Please provide more context to make the match unique.`,
181
157
  };
182
158
  }
183
- // Calculate diff info
184
- const oldStrLines = oldStr.split('\n').length;
185
- const newStrLines = newStr.split('\n').length;
186
- // Build diff lines
187
- const diffLines = [];
188
- for (const line of oldStr.split('\n')) {
189
- diffLines.push(`-${line}`);
190
- }
191
- for (const line of newStr.split('\n')) {
192
- diffLines.push(`+${line}`);
159
+ if (output === 'SUCCESS') {
160
+ return { msg: 'Successfully replaced text at exactly one location.' };
193
161
  }
194
- return {
195
- oldStart,
196
- oldLines: oldStrLines,
197
- newStart: oldStart,
198
- newLines: newStrLines,
199
- lines: diffLines,
200
- };
162
+ return { error: `Unexpected response: ${output}`, stderr: result.stderr };
201
163
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acontext/acontext",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "TypeScript SDK for the Acontext API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",