acontext 0.1.4__tar.gz → 0.1.5__tar.gz

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 (41) hide show
  1. {acontext-0.1.4 → acontext-0.1.5}/PKG-INFO +1 -1
  2. {acontext-0.1.4 → acontext-0.1.5}/pyproject.toml +1 -1
  3. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/agent/prompts.py +4 -1
  4. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/agent/sandbox.py +25 -10
  5. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/agent/text_editor.py +17 -4
  6. {acontext-0.1.4 → acontext-0.1.5}/README.md +0 -0
  7. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/__init__.py +0 -0
  8. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/_constants.py +0 -0
  9. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/_utils.py +0 -0
  10. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/agent/__init__.py +0 -0
  11. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/agent/base.py +0 -0
  12. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/agent/disk.py +0 -0
  13. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/agent/skill.py +0 -0
  14. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/async_client.py +0 -0
  15. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/client.py +0 -0
  16. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/client_types.py +0 -0
  17. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/errors.py +0 -0
  18. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/messages.py +0 -0
  19. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/py.typed +0 -0
  20. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/resources/__init__.py +0 -0
  21. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/resources/async_disks.py +0 -0
  22. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/resources/async_sandboxes.py +0 -0
  23. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/resources/async_sessions.py +0 -0
  24. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/resources/async_skills.py +0 -0
  25. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/resources/async_tools.py +0 -0
  26. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/resources/async_users.py +0 -0
  27. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/resources/disks.py +0 -0
  28. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/resources/sandboxes.py +0 -0
  29. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/resources/sessions.py +0 -0
  30. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/resources/skills.py +0 -0
  31. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/resources/tools.py +0 -0
  32. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/resources/users.py +0 -0
  33. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/types/__init__.py +0 -0
  34. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/types/common.py +0 -0
  35. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/types/disk.py +0 -0
  36. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/types/sandbox.py +0 -0
  37. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/types/session.py +0 -0
  38. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/types/skill.py +0 -0
  39. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/types/tool.py +0 -0
  40. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/types/user.py +0 -0
  41. {acontext-0.1.4 → acontext-0.1.5}/src/acontext/uploads.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: acontext
3
- Version: 0.1.4
3
+ Version: 0.1.5
4
4
  Summary: Python SDK for the Acontext API
5
5
  Keywords: acontext,sdk,client,api
6
6
  Requires-Dist: httpx>=0.28.1
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "acontext"
3
- version = "0.1.4"
3
+ version = "0.1.5"
4
4
  description = "Python SDK for the Acontext API"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -92,5 +92,8 @@ Container environment:
92
92
  - Standard Unix utilities available (grep, sed, awk, etc.)
93
93
  - Archive tools: tar, unzip, zip
94
94
  - Additional tools: ripgrep, fd, sqlite3, jq, imagemagick
95
- - Do not try to install new packages and libraries with pip as there is no internet access
95
+ - You can install new packages with pip if needed (internet access is available)
96
+
97
+
98
+ Remember to always export your artifacts at the end of your task so that the user can view them.
96
99
  """
@@ -10,6 +10,15 @@ from .prompts import SANDBOX_TEXT_EDITOR_REMINDER, SANDBOX_BASH_REMINDER, SKILL_
10
10
  from ..client import AcontextClient
11
11
  from ..async_client import AcontextAsyncClient
12
12
 
13
+ MAX_OUTPUT_CHARS = 20000
14
+
15
+
16
+ def truncate_output(text: str, max_chars: int = MAX_OUTPUT_CHARS) -> str:
17
+ """Truncate text to max_chars, appending a truncation flag if needed."""
18
+ if len(text) > max_chars:
19
+ return text[:max_chars] + "...[truncated]"
20
+ return text
21
+
13
22
 
14
23
  class MountedSkill(TypedDict):
15
24
  name: str
@@ -191,8 +200,8 @@ class BashTool(BaseTool):
191
200
 
192
201
  return json.dumps(
193
202
  {
194
- "stdout": result.stdout,
195
- "stderr": result.stderr,
203
+ "stdout": truncate_output(result.stdout),
204
+ "stderr": truncate_output(result.stderr),
196
205
  "exit_code": result.exit_code,
197
206
  }
198
207
  )
@@ -213,8 +222,8 @@ class BashTool(BaseTool):
213
222
 
214
223
  return json.dumps(
215
224
  {
216
- "stdout": result.stdout,
217
- "stderr": result.stderr,
225
+ "stdout": truncate_output(result.stdout),
226
+ "stderr": truncate_output(result.stderr),
218
227
  "exit_code": result.exit_code,
219
228
  }
220
229
  )
@@ -248,27 +257,33 @@ class TextEditorTool(BaseTool):
248
257
  "command": {
249
258
  "type": "string",
250
259
  "enum": ["view", "create", "str_replace"],
251
- "description": "The operation to perform: 'view', 'create', or 'str_replace'",
260
+ "description": (
261
+ "Perform only text operations: 'view', 'create', or 'str_replace'. "
262
+ "Required parameters per command: "
263
+ "'view' requires path (view_range is optional); "
264
+ "'create' requires path and file_text; "
265
+ "'str_replace' requires path, old_str, and new_str."
266
+ ),
252
267
  },
253
268
  "path": {
254
269
  "type": "string",
255
- "description": "The file path in the sandbox (e.g., '/workspace/script.py')",
270
+ "description": "Required for all commands. The file path in the sandbox (e.g., '/workspace/script.py')",
256
271
  },
257
272
  "file_text": {
258
273
  "type": ["string", "null"],
259
- "description": "For 'create' command: the content to write to the file",
274
+ "description": "Required for 'create' command. The content to write to the file.",
260
275
  },
261
276
  "old_str": {
262
277
  "type": ["string", "null"],
263
- "description": "For 'str_replace' command: the exact string to find and replace",
278
+ "description": "Required for 'str_replace' command. The exact string to find and replace.",
264
279
  },
265
280
  "new_str": {
266
281
  "type": ["string", "null"],
267
- "description": "For 'str_replace' command: the string to replace old_str with",
282
+ "description": "Required for 'str_replace' command. The string to replace old_str with.",
268
283
  },
269
284
  "view_range": {
270
285
  "type": ["array", "null"],
271
- "description": "For 'view' command: optional [start_line, end_line] to view specific lines",
286
+ "description": "Optional for 'view' command. An array [start_line, end_line] to view specific lines. If not provided, shows the first 200 lines.",
272
287
  },
273
288
  }
274
289
 
@@ -6,6 +6,15 @@ from typing import TYPE_CHECKING
6
6
  if TYPE_CHECKING:
7
7
  from .sandbox import AsyncSandboxContext, SandboxContext
8
8
 
9
+ MAX_CONTENT_CHARS = 20000
10
+
11
+
12
+ def truncate_content(text: str, max_chars: int = MAX_CONTENT_CHARS) -> str:
13
+ """Truncate text to max_chars, appending a truncation flag if needed."""
14
+ if len(text) > max_chars:
15
+ return text[:max_chars] + "...[truncated]"
16
+ return text
17
+
9
18
 
10
19
  def escape_for_shell(s: str) -> str:
11
20
  """Escape a string for safe use in shell commands."""
@@ -53,7 +62,9 @@ def view_file(
53
62
  start_line, end_line = view_range
54
63
  cmd = f"sed -n '{start_line},{end_line}p' {escape_for_shell(path)} | nl -ba -v {start_line}"
55
64
  else:
56
- cmd = f"nl -ba {escape_for_shell(path)}"
65
+ # Default to first 200 lines if no range specified
66
+ max_lines = 200
67
+ cmd = f"head -n {max_lines} {escape_for_shell(path)} | nl -ba"
57
68
  start_line = 1
58
69
 
59
70
  result = ctx.client.sandboxes.exec_command(
@@ -76,7 +87,7 @@ def view_file(
76
87
 
77
88
  return {
78
89
  "file_type": "text",
79
- "content": result.stdout,
90
+ "content": truncate_content(result.stdout),
80
91
  "numLines": num_lines,
81
92
  "startLine": start_line if view_range else 1,
82
93
  "totalLines": total_lines + 1, # wc -l doesn't count last line without newline
@@ -270,7 +281,9 @@ async def async_view_file(
270
281
  start_line, end_line = view_range
271
282
  cmd = f"sed -n '{start_line},{end_line}p' {escape_for_shell(path)} | nl -ba -v {start_line}"
272
283
  else:
273
- cmd = f"nl -ba {escape_for_shell(path)}"
284
+ # Default to first 200 lines if no range specified
285
+ max_lines = 200
286
+ cmd = f"head -n {max_lines} {escape_for_shell(path)} | nl -ba"
274
287
  start_line = 1
275
288
 
276
289
  result = await ctx.client.sandboxes.exec_command(
@@ -292,7 +305,7 @@ async def async_view_file(
292
305
 
293
306
  return {
294
307
  "file_type": "text",
295
- "content": result.stdout,
308
+ "content": truncate_content(result.stdout),
296
309
  "numLines": num_lines,
297
310
  "startLine": start_line if view_range else 1,
298
311
  "totalLines": total_lines + 1,
File without changes
File without changes