wcgw 2.6.3__tar.gz → 2.7.1__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.

Potentially problematic release.


This version of wcgw might be problematic. Click here for more details.

Files changed (157) hide show
  1. {wcgw-2.6.3 → wcgw-2.7.1}/PKG-INFO +14 -3
  2. {wcgw-2.6.3 → wcgw-2.7.1}/README.md +13 -2
  3. {wcgw-2.6.3 → wcgw-2.7.1}/gpt_action_json_schema.json +83 -0
  4. {wcgw-2.6.3 → wcgw-2.7.1}/gpt_instructions.txt +5 -0
  5. {wcgw-2.6.3 → wcgw-2.7.1}/pyproject.toml +1 -1
  6. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/anthropic_client.py +59 -51
  7. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/diff-instructions.txt +0 -1
  8. wcgw-2.7.1/src/wcgw/client/file_ops/diff_edit.py +482 -0
  9. wcgw-2.7.1/src/wcgw/client/file_ops/search_replace.py +119 -0
  10. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/mcp_server/server.py +45 -2
  11. wcgw-2.7.1/src/wcgw/client/memory.py +78 -0
  12. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/openai_client.py +38 -18
  13. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/tools.py +83 -169
  14. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/relay/serve.py +41 -12
  15. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/types_.py +8 -0
  16. wcgw-2.7.1/tests/client/file_ops/test_diff_edit.py +222 -0
  17. wcgw-2.7.1/tests/client/file_ops/test_search_replace.py +178 -0
  18. wcgw-2.7.1/tests/client/test_memory.py +78 -0
  19. wcgw-2.7.1/tests/client/test_tools_basic.py +22 -0
  20. {wcgw-2.6.3 → wcgw-2.7.1}/tests/client/test_tools_extended.py +18 -129
  21. wcgw-2.7.1/tests/client/test_tools_file_ops.py +155 -0
  22. wcgw-2.7.1/tests/client/test_tools_files.py +121 -0
  23. wcgw-2.7.1/tests/client/test_tools_shell.py +500 -0
  24. wcgw-2.7.1/tests/client/test_tools_validation.py +230 -0
  25. wcgw-2.7.1/tests/client/tools/__init__.py +1 -0
  26. wcgw-2.7.1/tests/client/tools/test_command_validation.py +125 -0
  27. wcgw-2.7.1/tests/client/tools/test_docker_operations.py +22 -0
  28. wcgw-2.7.1/tests/client/tools/test_error_handling.py +20 -0
  29. wcgw-2.7.1/tests/client/tools/test_execute_bash.py +71 -0
  30. wcgw-2.7.1/tests/client/tools/test_file_operations.py +156 -0
  31. wcgw-2.7.1/tests/client/tools/test_files/test1.py +4 -0
  32. wcgw-2.7.1/tests/client/tools/test_files/test2.py +4 -0
  33. wcgw-2.7.1/tests/client/tools/test_files/test_file.py +1 -0
  34. wcgw-2.7.1/tests/client/tools/test_is_int.py +25 -0
  35. wcgw-2.7.1/tests/client/tools/test_knowledge_transfer.py +155 -0
  36. wcgw-2.7.1/tests/client/tools/test_large_blocks.py +21 -0
  37. wcgw-2.7.1/tests/client/tools/test_render_terminal.py +25 -0
  38. wcgw-2.7.1/tests/client/tools/test_terminal_output.py +187 -0
  39. wcgw-2.7.1/tests/client/tools/test_user_interaction.py +116 -0
  40. wcgw-2.7.1/tests/client/tools/test_write_file.py +112 -0
  41. wcgw-2.7.1/tests/conftest.py +12 -0
  42. {wcgw-2.6.3 → wcgw-2.7.1}/uv.lock +1 -1
  43. wcgw-2.6.3/tests/client/test_tools_basic.py +0 -57
  44. {wcgw-2.6.3 → wcgw-2.7.1}/.github/workflows/python-publish.yml +0 -0
  45. {wcgw-2.6.3 → wcgw-2.7.1}/.github/workflows/python-tests.yml +0 -0
  46. {wcgw-2.6.3 → wcgw-2.7.1}/.github/workflows/python-types.yml +0 -0
  47. {wcgw-2.6.3 → wcgw-2.7.1}/.gitignore +0 -0
  48. {wcgw-2.6.3 → wcgw-2.7.1}/.gitmodules +0 -0
  49. {wcgw-2.6.3 → wcgw-2.7.1}/.python-version +0 -0
  50. {wcgw-2.6.3 → wcgw-2.7.1}/.vscode/settings.json +0 -0
  51. {wcgw-2.6.3 → wcgw-2.7.1}/LICENSE +0 -0
  52. {wcgw-2.6.3 → wcgw-2.7.1}/openai.md +0 -0
  53. {wcgw-2.6.3 → wcgw-2.7.1}/src/__init__.py +0 -0
  54. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/.git +0 -0
  55. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  56. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  57. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/.github/workflows/main-checks.yml +0 -0
  58. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/.github/workflows/publish-pypi.yml +0 -0
  59. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/.github/workflows/pull-request-checks.yml +0 -0
  60. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/.github/workflows/shared.yml +0 -0
  61. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/.gitignore +0 -0
  62. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/.python-version +0 -0
  63. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/CODE_OF_CONDUCT.md +0 -0
  64. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/CONTRIBUTING.md +0 -0
  65. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/LICENSE +0 -0
  66. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/README.md +0 -0
  67. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/RELEASE.md +0 -0
  68. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/SECURITY.md +0 -0
  69. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/README.md +0 -0
  70. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-prompt/.python-version +0 -0
  71. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-prompt/README.md +0 -0
  72. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-prompt/mcp_simple_prompt/__init__.py +0 -0
  73. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-prompt/mcp_simple_prompt/__main__.py +0 -0
  74. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-prompt/mcp_simple_prompt/server.py +0 -0
  75. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-prompt/pyproject.toml +0 -0
  76. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-resource/.python-version +0 -0
  77. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-resource/README.md +0 -0
  78. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-resource/mcp_simple_resource/__init__.py +0 -0
  79. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-resource/mcp_simple_resource/__main__.py +0 -0
  80. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-resource/mcp_simple_resource/server.py +0 -0
  81. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-resource/pyproject.toml +0 -0
  82. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-tool/.python-version +0 -0
  83. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-tool/README.md +0 -0
  84. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-tool/mcp_simple_tool/__init__.py +0 -0
  85. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-tool/mcp_simple_tool/__main__.py +0 -0
  86. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-tool/mcp_simple_tool/server.py +0 -0
  87. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/examples/servers/simple-tool/pyproject.toml +0 -0
  88. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/pyproject.toml +0 -0
  89. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/__init__.py +0 -0
  90. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/client/__init__.py +0 -0
  91. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/client/__main__.py +0 -0
  92. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/client/session.py +0 -0
  93. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/client/sse.py +0 -0
  94. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/client/stdio.py +0 -0
  95. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/py.typed +0 -0
  96. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/server/__init__.py +0 -0
  97. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/server/__main__.py +0 -0
  98. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/server/models.py +0 -0
  99. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/server/session.py +0 -0
  100. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/server/sse.py +0 -0
  101. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/server/stdio.py +0 -0
  102. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/server/websocket.py +0 -0
  103. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/shared/__init__.py +0 -0
  104. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/shared/context.py +0 -0
  105. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/shared/exceptions.py +0 -0
  106. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/shared/memory.py +0 -0
  107. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/shared/progress.py +0 -0
  108. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/shared/session.py +0 -0
  109. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/shared/version.py +0 -0
  110. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/src/mcp_wcgw/types.py +0 -0
  111. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/tests/__init__.py +0 -0
  112. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/tests/client/__init__.py +0 -0
  113. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/tests/client/test_session.py +0 -0
  114. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/tests/client/test_stdio.py +0 -0
  115. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/tests/conftest.py +0 -0
  116. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/tests/server/__init__.py +0 -0
  117. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/tests/server/test_session.py +0 -0
  118. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/tests/server/test_stdio.py +0 -0
  119. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/tests/shared/test_memory.py +0 -0
  120. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/tests/test_types.py +0 -0
  121. {wcgw-2.6.3 → wcgw-2.7.1}/src/mcp_wcgw/uv.lock +0 -0
  122. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/__init__.py +0 -0
  123. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/__init__.py +0 -0
  124. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/__main__.py +0 -0
  125. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/cli.py +0 -0
  126. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/common.py +0 -0
  127. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/computer_use.py +0 -0
  128. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/mcp_server/Readme.md +0 -0
  129. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/mcp_server/__init__.py +0 -0
  130. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/openai_utils.py +0 -0
  131. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/repo_ops/display_tree.py +0 -0
  132. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/repo_ops/path_prob.py +0 -0
  133. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/repo_ops/paths_model.vocab +0 -0
  134. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/repo_ops/paths_tokens.model +0 -0
  135. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/repo_ops/repo_context.py +0 -0
  136. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/client/sys_utils.py +0 -0
  137. {wcgw-2.6.3 → wcgw-2.7.1}/src/wcgw/relay/static/privacy.txt +0 -0
  138. {wcgw-2.6.3 → wcgw-2.7.1}/static/claude-ss.jpg +0 -0
  139. {wcgw-2.6.3 → wcgw-2.7.1}/static/computer-use.jpg +0 -0
  140. {wcgw-2.6.3 → wcgw-2.7.1}/static/example.jpg +0 -0
  141. {wcgw-2.6.3 → wcgw-2.7.1}/static/rocket-icon.png +0 -0
  142. {wcgw-2.6.3 → wcgw-2.7.1}/static/ss1.png +0 -0
  143. {wcgw-2.6.3 → wcgw-2.7.1}/tests/client/repo_ops/__init__.py +0 -0
  144. {wcgw-2.6.3 → wcgw-2.7.1}/tests/client/repo_ops/test_display_tree.py +0 -0
  145. {wcgw-2.6.3 → wcgw-2.7.1}/tests/client/repo_ops/test_display_tree_simple.py +0 -0
  146. {wcgw-2.6.3 → wcgw-2.7.1}/tests/client/repo_ops/test_path_prob.py +0 -0
  147. {wcgw-2.6.3 → wcgw-2.7.1}/tests/client/repo_ops/test_repo_context.py +0 -0
  148. {wcgw-2.6.3 → wcgw-2.7.1}/tests/client/test_anthropic_client_utils.py +0 -0
  149. {wcgw-2.6.3 → wcgw-2.7.1}/tests/client/test_openai_utils.py +0 -0
  150. {wcgw-2.6.3 → wcgw-2.7.1}/tests/test_anthropic_client.py +0 -0
  151. {wcgw-2.6.3 → wcgw-2.7.1}/tests/test_basic.py +0 -0
  152. {wcgw-2.6.3 → wcgw-2.7.1}/tests/test_common.py +0 -0
  153. {wcgw-2.6.3 → wcgw-2.7.1}/tests/test_computer_use.py +0 -0
  154. {wcgw-2.6.3 → wcgw-2.7.1}/tests/test_computer_use_base.py +0 -0
  155. {wcgw-2.6.3 → wcgw-2.7.1}/tests/test_computer_use_shell.py +0 -0
  156. {wcgw-2.6.3 → wcgw-2.7.1}/tests/test_sys_utils.py +0 -0
  157. {wcgw-2.6.3 → wcgw-2.7.1}/tests/test_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wcgw
3
- Version: 2.6.3
3
+ Version: 2.7.1
4
4
  Summary: Shell and coding agent on claude and chatgpt
5
5
  Project-URL: Homepage, https://github.com/rusiaaman/wcgw
6
6
  Author-email: Aman Rusia <gapypi@arcfu.com>
@@ -33,7 +33,7 @@ Description-Content-Type: text/markdown
33
33
  - Chatgpt - Allows custom gpt to talk to your shell via a relay server. (linux or mac)
34
34
 
35
35
 
36
- ⚠️ Warning: do not use this repo if you aren't scared of "Autonomous shell command execution"
36
+ ⚠️ Warning: do not allow BashCommand tool without reviewing the command, it may result in data loss.
37
37
 
38
38
  [![Tests](https://github.com/rusiaaman/wcgw/actions/workflows/python-tests.yml/badge.svg?branch=main)](https://github.com/rusiaaman/wcgw/actions/workflows/python-tests.yml)
39
39
  [![Mypy strict](https://github.com/rusiaaman/wcgw/actions/workflows/python-types.yml/badge.svg?branch=main)](https://github.com/rusiaaman/wcgw/actions/workflows/python-types.yml)
@@ -55,7 +55,18 @@ Description-Content-Type: text/markdown
55
55
  - ⚡ **Large file edit**: Supports large file incremental edits to avoid token limit issues. Faster than full file write.
56
56
  - ⚡ **Syntax checking on edits**: Reports feedback to the LLM if its edits have any syntax errors, so that it can redo it.
57
57
  - ⚡ **Interactive Command Handling**: Supports interactive commands using arrow keys, interrupt, and ansi escape sequences.
58
- - ⚡ **Full Shell Access**: No restrictions, complete control.
58
+ - ⚡ **File protections**:
59
+ - The AI needs to read a file at least once before it's allowed to edit or rewrite it. This avoids accidental overwrites.
60
+ - Avoids context filling up while reading very large files. Files get chunked based on token length.
61
+ - On initialisation the provided workspace's directory structure is returned after selecting important files (based on .gitignore as well as a statistical approach)
62
+ - File edit based on search-replace tries to find correct search block if it has multiple matches based on previous search blocks. Fails otherwise (for correctness).
63
+ - File edit has spacing tolerant matching, with warning on issues like indentation mismatch. If there's no match, the closest match is returned to the AI to fix its mistakes.
64
+ - Using Aider-like search and replace, which has better performance than tool call based search and replace.
65
+ - ⚡ **Shell optimisations**:
66
+ - Only one command is allowed to be run at a time, simplifying management and avoiding rogue processes. There's only single shell instance at any point of time.
67
+ - Current working directory is always returned after any shell command to prevent AI from getting lost.
68
+ - Command polling exits after a quick timeout to avoid slow feedback. However, status checking has wait tolerance based on fresh output streaming from a command. Both of these approach combined provides a good shell interaction experience.
69
+
59
70
 
60
71
  ## Top use cases examples
61
72
 
@@ -4,7 +4,7 @@
4
4
  - Chatgpt - Allows custom gpt to talk to your shell via a relay server. (linux or mac)
5
5
 
6
6
 
7
- ⚠️ Warning: do not use this repo if you aren't scared of "Autonomous shell command execution"
7
+ ⚠️ Warning: do not allow BashCommand tool without reviewing the command, it may result in data loss.
8
8
 
9
9
  [![Tests](https://github.com/rusiaaman/wcgw/actions/workflows/python-tests.yml/badge.svg?branch=main)](https://github.com/rusiaaman/wcgw/actions/workflows/python-tests.yml)
10
10
  [![Mypy strict](https://github.com/rusiaaman/wcgw/actions/workflows/python-types.yml/badge.svg?branch=main)](https://github.com/rusiaaman/wcgw/actions/workflows/python-types.yml)
@@ -26,7 +26,18 @@
26
26
  - ⚡ **Large file edit**: Supports large file incremental edits to avoid token limit issues. Faster than full file write.
27
27
  - ⚡ **Syntax checking on edits**: Reports feedback to the LLM if its edits have any syntax errors, so that it can redo it.
28
28
  - ⚡ **Interactive Command Handling**: Supports interactive commands using arrow keys, interrupt, and ansi escape sequences.
29
- - ⚡ **Full Shell Access**: No restrictions, complete control.
29
+ - ⚡ **File protections**:
30
+ - The AI needs to read a file at least once before it's allowed to edit or rewrite it. This avoids accidental overwrites.
31
+ - Avoids context filling up while reading very large files. Files get chunked based on token length.
32
+ - On initialisation the provided workspace's directory structure is returned after selecting important files (based on .gitignore as well as a statistical approach)
33
+ - File edit based on search-replace tries to find correct search block if it has multiple matches based on previous search blocks. Fails otherwise (for correctness).
34
+ - File edit has spacing tolerant matching, with warning on issues like indentation mismatch. If there's no match, the closest match is returned to the AI to fix its mistakes.
35
+ - Using Aider-like search and replace, which has better performance than tool call based search and replace.
36
+ - ⚡ **Shell optimisations**:
37
+ - Only one command is allowed to be run at a time, simplifying management and avoiding rogue processes. There's only single shell instance at any point of time.
38
+ - Current working directory is always returned after any shell command to prevent AI from getting lost.
39
+ - Command polling exits after a quick timeout to avoid slow feedback. However, status checking has wait tolerance based on fresh output streaming from a command. Both of these approach combined provides a good shell interaction experience.
40
+
30
41
 
31
42
  ## Top use cases examples
32
43
 
@@ -289,6 +289,46 @@
289
289
  }
290
290
  }
291
291
  }
292
+ },
293
+ "/v1/context_save": {
294
+ "post": {
295
+ "x-openai-isConsequential": false,
296
+ "summary": "Context Save",
297
+ "operationId": "context_save_v1_context_save_post",
298
+ "requestBody": {
299
+ "content": {
300
+ "application/json": {
301
+ "schema": {
302
+ "$ref": "#/components/schemas/ContextSaveWithUUID"
303
+ }
304
+ }
305
+ },
306
+ "required": true
307
+ },
308
+ "responses": {
309
+ "200": {
310
+ "description": "Successful Response",
311
+ "content": {
312
+ "application/json": {
313
+ "schema": {
314
+ "type": "string",
315
+ "title": "Response Context Save V1 Context Save Post"
316
+ }
317
+ }
318
+ }
319
+ },
320
+ "422": {
321
+ "description": "Validation Error",
322
+ "content": {
323
+ "application/json": {
324
+ "schema": {
325
+ "$ref": "#/components/schemas/HTTPValidationError"
326
+ }
327
+ }
328
+ }
329
+ }
330
+ }
331
+ }
292
332
  }
293
333
  },
294
334
  "components": {
@@ -387,6 +427,44 @@
387
427
  ],
388
428
  "title": "CommandWithUUID"
389
429
  },
430
+ "ContextSaveWithUUID": {
431
+ "properties": {
432
+ "id": {
433
+ "type": "string",
434
+ "title": "Id"
435
+ },
436
+ "project_root_path": {
437
+ "type": "string",
438
+ "title": "Project Root Path"
439
+ },
440
+ "description": {
441
+ "type": "string",
442
+ "title": "Description"
443
+ },
444
+ "relevant_file_globs": {
445
+ "items": {
446
+ "type": "string"
447
+ },
448
+ "type": "array",
449
+ "title": "Relevant File Globs"
450
+ },
451
+ "user_id": {
452
+ "type": "string",
453
+ "format": "uuid",
454
+ "title": "User Id"
455
+ }
456
+ },
457
+ "additionalProperties": false,
458
+ "type": "object",
459
+ "required": [
460
+ "id",
461
+ "project_root_path",
462
+ "description",
463
+ "relevant_file_globs",
464
+ "user_id"
465
+ ],
466
+ "title": "ContextSaveWithUUID"
467
+ },
390
468
  "FileEditWithUUID": {
391
469
  "properties": {
392
470
  "file_path": {
@@ -438,6 +516,10 @@
438
516
  "type": "array",
439
517
  "title": "Initial Files To Read"
440
518
  },
519
+ "task_id_to_resume": {
520
+ "type": "string",
521
+ "title": "Task Id To Resume"
522
+ },
441
523
  "user_id": {
442
524
  "type": "string",
443
525
  "format": "uuid",
@@ -449,6 +531,7 @@
449
531
  "required": [
450
532
  "any_workspace_path",
451
533
  "initial_files_to_read",
534
+ "task_id_to_resume",
452
535
  "user_id"
453
536
  ],
454
537
  "title": "InitializeWithUUID"
@@ -44,6 +44,11 @@ Instructions for `BashInteraction`
44
44
  Instructions for `ResetShell`
45
45
  - Resets the shell. Use only if all interrupts and prompt reset attempts have failed repeatedly.
46
46
 
47
+ Instructions for `ContextSave`
48
+ - Saves provided description and file contents of all the relevant file paths or globs in a single text file.
49
+ - Provide random unqiue id or whatever user provided.
50
+ - Leave project path as empty string if no project path
51
+
47
52
  Instructions for `FileEdit`:
48
53
  - Use absolute file path only.
49
54
  - Use SEARCH/REPLACE blocks to edit the file.
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  authors = [{ name = "Aman Rusia", email = "gapypi@arcfu.com" }]
3
3
  name = "wcgw"
4
- version = "2.6.3"
4
+ version = "2.7.1"
5
5
  description = "Shell and coding agent on claude and chatgpt"
6
6
  readme = "README.md"
7
7
  requires-python = ">=3.11, <3.13"
@@ -1,59 +1,51 @@
1
1
  import base64
2
2
  import json
3
3
  import mimetypes
4
- from pathlib import Path
5
- import sys
4
+ import os
5
+ import subprocess
6
+ import tempfile
6
7
  import traceback
7
- from typing import Callable, DefaultDict, Optional, cast, Literal
8
- import anthropic
8
+ import uuid
9
+ from pathlib import Path
10
+ from typing import Literal, Optional, cast
11
+
12
+ import rich
9
13
  from anthropic import Anthropic
10
14
  from anthropic.types import (
11
- ToolParam,
15
+ ImageBlockParam,
12
16
  MessageParam,
17
+ TextBlockParam,
18
+ ToolParam,
13
19
  ToolResultBlockParam,
14
20
  ToolUseBlockParam,
15
- ImageBlockParam,
16
- TextBlockParam,
17
21
  )
18
-
19
- import rich
20
- import petname # type: ignore[import-untyped]
22
+ from dotenv import load_dotenv
21
23
  from typer import Typer
22
- import uuid
23
24
 
24
25
  from ..types_ import (
25
26
  BashCommand,
26
27
  BashInteraction,
27
- WriteIfEmpty,
28
- FileEditFindReplace,
28
+ ContextSave,
29
29
  FileEdit,
30
+ GetScreenInfo,
30
31
  Keyboard,
31
32
  Mouse,
32
33
  ReadFiles,
33
34
  ReadImage,
34
35
  ResetShell,
35
36
  ScreenShot,
36
- GetScreenInfo,
37
+ WriteIfEmpty,
38
+ )
39
+ from .common import discard_input
40
+ from .memory import load_memory
41
+ from .tools import (
42
+ DoneFlag,
43
+ ImageData,
44
+ default_enc,
45
+ get_tool_output,
46
+ initialize,
47
+ which_tool_name,
37
48
  )
38
-
39
- from .common import Models, discard_input
40
- from .common import CostData
41
- from .tools import ImageData
42
- from .computer_use import Computer
43
-
44
- from .tools import DoneFlag, get_tool_output, which_tool_name, default_enc
45
-
46
- from urllib import parse
47
- import subprocess
48
- import os
49
- import tempfile
50
-
51
- import toml
52
- from pydantic import BaseModel
53
-
54
-
55
- from dotenv import load_dotenv
56
-
57
49
 
58
50
  History = list[MessageParam]
59
51
 
@@ -135,19 +127,28 @@ def loop(
135
127
 
136
128
  history: History = []
137
129
  waiting_for_assistant = False
130
+ memory = None
138
131
  if resume:
139
- if resume == "latest":
140
- resume_path = sorted(Path(".wcgw").iterdir(), key=os.path.getmtime)[-1]
141
- else:
142
- resume_path = Path(resume)
143
- if not resume_path.exists():
144
- raise FileNotFoundError(f"File {resume} not found")
145
- with resume_path.open() as f:
146
- history = json.load(f)
147
- if len(history) <= 2:
148
- raise ValueError("Invalid history file")
149
- first_message = ""
150
- waiting_for_assistant = history[-1]["role"] != "assistant"
132
+ try:
133
+ _, memory = load_memory(
134
+ resume,
135
+ 8000,
136
+ lambda x: default_enc.encode(x).ids,
137
+ lambda x: default_enc.decode(x),
138
+ )
139
+ except OSError:
140
+ if resume == "latest":
141
+ resume_path = sorted(Path(".wcgw").iterdir(), key=os.path.getmtime)[-1]
142
+ else:
143
+ resume_path = Path(resume)
144
+ if not resume_path.exists():
145
+ raise FileNotFoundError(f"File {resume} not found")
146
+ with resume_path.open() as f:
147
+ history = json.load(f)
148
+ if len(history) <= 2:
149
+ raise ValueError("Invalid history file")
150
+ first_message = ""
151
+ waiting_for_assistant = history[-1]["role"] != "assistant"
151
152
 
152
153
  limit = 1
153
154
 
@@ -216,6 +217,15 @@ def loop(
216
217
  - Use absolute file path only.
217
218
  - Use SEARCH/REPLACE blocks to edit the file.
218
219
  - If the edit fails due to block not matching, please retry with correct block till it matches. Re-read the file to ensure you've all the lines correct.
220
+ """,
221
+ ),
222
+ ToolParam(
223
+ input_schema=ContextSave.model_json_schema(),
224
+ name="ContextSave",
225
+ description="""
226
+ Saves provided description and file contents of all the relevant file paths or globs in a single text file.
227
+ - Provide random unqiue id or whatever user provided.
228
+ - Leave project path as empty string if no project path
219
229
  """,
220
230
  ),
221
231
  ]
@@ -270,9 +280,10 @@ def loop(
270
280
  """,
271
281
  ),
272
282
  ]
273
- uname_sysname = os.uname().sysname
274
- uname_machine = os.uname().machine
275
283
 
284
+ initial_info = initialize(
285
+ os.getcwd(), [], resume if (memory and resume) else "", 8000
286
+ )
276
287
  system = f"""
277
288
  You're an expert software engineer with shell and code knowledge.
278
289
 
@@ -284,10 +295,7 @@ Instructions:
284
295
  - Do not provide code snippets unless asked by the user, instead directly add/edit the code.
285
296
  - Do not install new tools/packages before ensuring no such tools/package or an alternative already exists.
286
297
 
287
- System information:
288
- - System: {uname_sysname}
289
- - Machine: {uname_machine}
290
- - Current directory: {os.getcwd()}
298
+ {initial_info}
291
299
  """
292
300
 
293
301
  with open(os.path.join(os.path.dirname(__file__), "diff-instructions.txt")) as f:
@@ -47,7 +47,6 @@ Every *SEARCH/REPLACE block* must use this format:
47
47
 
48
48
  Every "<<<<<<< SEARCH" section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, whitespaces, etc.
49
49
 
50
- *SEARCH/REPLACE* blocks will *only* replace the first match occurrence.
51
50
  Including multiple unique *SEARCH/REPLACE* blocks if needed.
52
51
  Include enough lines in each SEARCH section to uniquely match each set of lines that need to change.
53
52