wcgw 2.8.7__tar.gz → 2.8.9__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.
- {wcgw-2.8.7 → wcgw-2.8.9}/PKG-INFO +1 -1
- {wcgw-2.8.7 → wcgw-2.8.9}/pyproject.toml +1 -1
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/tools.py +15 -3
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw_cli/anthropic_client.py +82 -10
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/test_initialize.py +75 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/.github/workflows/python-publish.yml +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/.github/workflows/python-tests.yml +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/.github/workflows/python-types.yml +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/.gitignore +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/.gitmodules +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/.python-version +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/.vscode/settings.json +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/Dockerfile +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/LICENSE +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/README.md +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/gpt_action_json_schema.json +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/gpt_instructions.txt +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/openai.md +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/.git +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/.github/workflows/main-checks.yml +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/.github/workflows/publish-pypi.yml +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/.github/workflows/pull-request-checks.yml +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/.github/workflows/shared.yml +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/.gitignore +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/.python-version +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/CODE_OF_CONDUCT.md +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/CONTRIBUTING.md +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/LICENSE +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/README.md +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/RELEASE.md +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/SECURITY.md +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/README.md +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-prompt/.python-version +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-prompt/README.md +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-prompt/mcp_simple_prompt/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-prompt/mcp_simple_prompt/__main__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-prompt/mcp_simple_prompt/server.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-prompt/pyproject.toml +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-resource/.python-version +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-resource/README.md +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-resource/mcp_simple_resource/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-resource/mcp_simple_resource/__main__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-resource/mcp_simple_resource/server.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-resource/pyproject.toml +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-tool/.python-version +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-tool/README.md +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-tool/mcp_simple_tool/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-tool/mcp_simple_tool/__main__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-tool/mcp_simple_tool/server.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-tool/pyproject.toml +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/pyproject.toml +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/client/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/client/__main__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/client/session.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/client/sse.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/client/stdio.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/py.typed +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/server/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/server/__main__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/server/models.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/server/session.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/server/sse.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/server/stdio.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/server/websocket.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/shared/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/shared/context.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/shared/exceptions.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/shared/memory.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/shared/progress.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/shared/session.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/shared/version.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/src/mcp_wcgw/types.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/tests/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/tests/client/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/tests/client/test_session.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/tests/client/test_stdio.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/tests/conftest.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/tests/server/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/tests/server/test_session.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/tests/server/test_stdio.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/tests/shared/test_memory.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/tests/test_types.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/uv.lock +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/common.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/computer_use.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/diff-instructions.txt +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/file_ops/diff_edit.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/file_ops/search_replace.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/mcp_server/Readme.md +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/mcp_server/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/mcp_server/server.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/memory.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/modes.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/repo_ops/display_tree.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/repo_ops/path_prob.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/repo_ops/paths_model.vocab +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/repo_ops/paths_tokens.model +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/repo_ops/repo_context.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/client/sys_utils.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/relay/serve.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/relay/static/privacy.txt +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw/types_.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw_cli/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw_cli/__main__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw_cli/cli.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw_cli/openai_client.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/src/wcgw_cli/openai_utils.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/static/claude-ss.jpg +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/static/computer-use.jpg +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/static/example.jpg +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/static/rocket-icon.png +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/static/ss1.png +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/file_ops/test_diff_edit.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/file_ops/test_search_replace.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/repo_ops/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/repo_ops/test_display_tree.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/repo_ops/test_display_tree_simple.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/repo_ops/test_path_prob.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/repo_ops/test_repo_context.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/test_anthropic_client_utils.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/test_memory.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/test_openai_utils.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/test_tools_basic.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/test_tools_extended.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/test_tools_file_ops.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/test_tools_files.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/test_tools_shell.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/test_tools_validation.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/__init__.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_command_validation.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_docker_operations.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_error_handling.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_error_handling_full.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_execute_bash.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_file_errors.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_file_operations.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_files/test1.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_files/test2.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_files/test_file.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_full_coverage.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_is_int.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_knowledge_transfer.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_large_blocks.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_prompt_update.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_render_terminal.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_terminal_output.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_terminal_output_full.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_terminal_output_incremental.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_terminal_output_raw.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_terminal_sequence.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_timeout_handling.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_timeout_state.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_user_interaction.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/client/tools/test_write_file.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/conftest.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/test_anthropic_client.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/test_basic.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/test_common.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/test_computer_use.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/test_computer_use_base.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/test_computer_use_shell.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/test_sys_utils.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/tests/test_tools.py +0 -0
- {wcgw-2.8.7 → wcgw-2.8.9}/uv.lock +0 -0
|
@@ -146,6 +146,7 @@ def start_shell(is_restricted_mode: bool, initial_dir: str) -> pexpect.spawn: #
|
|
|
146
146
|
encoding="utf-8",
|
|
147
147
|
timeout=TIMEOUT,
|
|
148
148
|
cwd=initial_dir,
|
|
149
|
+
codec_errors="backslashreplace",
|
|
149
150
|
)
|
|
150
151
|
shell.sendline(
|
|
151
152
|
f"export PROMPT_COMMAND= PS1={PROMPT_CONST}"
|
|
@@ -161,6 +162,7 @@ def start_shell(is_restricted_mode: bool, initial_dir: str) -> pexpect.spawn: #
|
|
|
161
162
|
echo=False,
|
|
162
163
|
encoding="utf-8",
|
|
163
164
|
timeout=TIMEOUT,
|
|
165
|
+
codec_errors="backslashreplace",
|
|
164
166
|
)
|
|
165
167
|
shell.sendline(f"export PS1={PROMPT_CONST}")
|
|
166
168
|
shell.expect(PROMPT_CONST, timeout=TIMEOUT)
|
|
@@ -256,7 +258,9 @@ class BashState:
|
|
|
256
258
|
before = "\n".join(before_lines).strip()
|
|
257
259
|
counts += 1
|
|
258
260
|
if counts > 100:
|
|
259
|
-
raise ValueError(
|
|
261
|
+
raise ValueError(
|
|
262
|
+
"Error in understanding shell output. This shouldn't happen, likely shell is in a bad state, please reset it"
|
|
263
|
+
)
|
|
260
264
|
|
|
261
265
|
try:
|
|
262
266
|
return int(before)
|
|
@@ -273,7 +277,7 @@ class BashState:
|
|
|
273
277
|
self._bash_command_mode.bash_mode == "restricted_mode",
|
|
274
278
|
self._cwd,
|
|
275
279
|
)
|
|
276
|
-
|
|
280
|
+
|
|
277
281
|
self._pending_output = ""
|
|
278
282
|
|
|
279
283
|
# Get exit info to ensure shell is ready
|
|
@@ -414,7 +418,9 @@ class BashState:
|
|
|
414
418
|
index = self.shell.expect([self._prompt, pexpect.TIMEOUT], timeout=0.2)
|
|
415
419
|
counts += 1
|
|
416
420
|
if counts > 100:
|
|
417
|
-
raise ValueError(
|
|
421
|
+
raise ValueError(
|
|
422
|
+
"Error in understanding shell output. This shouldn't happen, likely shell is in a bad state, please reset it"
|
|
423
|
+
)
|
|
418
424
|
console.print(f"Prompt updated to: {self._prompt}")
|
|
419
425
|
return True
|
|
420
426
|
return False
|
|
@@ -457,6 +463,12 @@ def initialize(
|
|
|
457
463
|
folder_to_start = None
|
|
458
464
|
if any_workspace_path:
|
|
459
465
|
if os.path.exists(any_workspace_path):
|
|
466
|
+
if os.path.isfile(any_workspace_path):
|
|
467
|
+
# Set any_workspace_path to the directory containing the file
|
|
468
|
+
# Add the file to read_files_ only if empty to avoid duplicates
|
|
469
|
+
if not read_files_:
|
|
470
|
+
read_files_ = [any_workspace_path]
|
|
471
|
+
any_workspace_path = os.path.dirname(any_workspace_path)
|
|
460
472
|
repo_context, folder_to_start = get_repo_context(any_workspace_path, 200)
|
|
461
473
|
|
|
462
474
|
repo_context = f"---\n# Workspace structure\n{repo_context}\n---\n"
|
|
@@ -14,15 +14,17 @@ from anthropic import Anthropic
|
|
|
14
14
|
from anthropic.types import (
|
|
15
15
|
ImageBlockParam,
|
|
16
16
|
MessageParam,
|
|
17
|
+
ModelParam,
|
|
17
18
|
TextBlockParam,
|
|
18
19
|
ToolParam,
|
|
19
20
|
ToolResultBlockParam,
|
|
20
21
|
ToolUseBlockParam,
|
|
21
22
|
)
|
|
22
23
|
from dotenv import load_dotenv
|
|
24
|
+
from pydantic import BaseModel
|
|
23
25
|
from typer import Typer
|
|
24
26
|
|
|
25
|
-
from wcgw.client.common import discard_input
|
|
27
|
+
from wcgw.client.common import CostData, discard_input
|
|
26
28
|
from wcgw.client.memory import load_memory
|
|
27
29
|
from wcgw.client.tools import (
|
|
28
30
|
DoneFlag,
|
|
@@ -47,6 +49,14 @@ from wcgw.types_ import (
|
|
|
47
49
|
WriteIfEmpty,
|
|
48
50
|
)
|
|
49
51
|
|
|
52
|
+
|
|
53
|
+
class Config(BaseModel):
|
|
54
|
+
model: ModelParam
|
|
55
|
+
cost_limit: float
|
|
56
|
+
cost_file: dict[ModelParam, CostData]
|
|
57
|
+
cost_unit: str = "$"
|
|
58
|
+
|
|
59
|
+
|
|
50
60
|
History = list[MessageParam]
|
|
51
61
|
|
|
52
62
|
|
|
@@ -150,7 +160,51 @@ def loop(
|
|
|
150
160
|
first_message = ""
|
|
151
161
|
waiting_for_assistant = history[-1]["role"] != "assistant"
|
|
152
162
|
|
|
153
|
-
|
|
163
|
+
config = Config(
|
|
164
|
+
model="claude-3-5-sonnet-20241022",
|
|
165
|
+
cost_limit=0.1,
|
|
166
|
+
cost_unit="$",
|
|
167
|
+
cost_file={
|
|
168
|
+
# Claude 3.5 Haiku
|
|
169
|
+
"claude-3-5-haiku-latest": CostData(
|
|
170
|
+
cost_per_1m_input_tokens=0.80, cost_per_1m_output_tokens=4
|
|
171
|
+
),
|
|
172
|
+
"claude-3-5-haiku-20241022": CostData(
|
|
173
|
+
cost_per_1m_input_tokens=0.80, cost_per_1m_output_tokens=4
|
|
174
|
+
),
|
|
175
|
+
# Claude 3.5 Sonnet
|
|
176
|
+
"claude-3-5-sonnet-latest": CostData(
|
|
177
|
+
cost_per_1m_input_tokens=3.0, cost_per_1m_output_tokens=15.0
|
|
178
|
+
),
|
|
179
|
+
"claude-3-5-sonnet-20241022": CostData(
|
|
180
|
+
cost_per_1m_input_tokens=3.0, cost_per_1m_output_tokens=15.0
|
|
181
|
+
),
|
|
182
|
+
"claude-3-5-sonnet-20240620": CostData(
|
|
183
|
+
cost_per_1m_input_tokens=3.0, cost_per_1m_output_tokens=15.0
|
|
184
|
+
),
|
|
185
|
+
# Claude 3 Opus
|
|
186
|
+
"claude-3-opus-latest": CostData(
|
|
187
|
+
cost_per_1m_input_tokens=15.0, cost_per_1m_output_tokens=75.0
|
|
188
|
+
),
|
|
189
|
+
"claude-3-opus-20240229": CostData(
|
|
190
|
+
cost_per_1m_input_tokens=15.0, cost_per_1m_output_tokens=75.0
|
|
191
|
+
),
|
|
192
|
+
# Legacy Models
|
|
193
|
+
"claude-3-haiku-20240307": CostData(
|
|
194
|
+
cost_per_1m_input_tokens=0.25, cost_per_1m_output_tokens=1.25
|
|
195
|
+
),
|
|
196
|
+
"claude-2.1": CostData(
|
|
197
|
+
cost_per_1m_input_tokens=8.0, cost_per_1m_output_tokens=24.0
|
|
198
|
+
),
|
|
199
|
+
"claude-2.0": CostData(
|
|
200
|
+
cost_per_1m_input_tokens=8.0, cost_per_1m_output_tokens=24.0
|
|
201
|
+
),
|
|
202
|
+
},
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
if limit is not None:
|
|
206
|
+
config.cost_limit = limit
|
|
207
|
+
limit = config.cost_limit
|
|
154
208
|
|
|
155
209
|
tools = [
|
|
156
210
|
ToolParam(
|
|
@@ -321,9 +375,15 @@ Saves provided description and file contents of all the relevant file paths or g
|
|
|
321
375
|
while True:
|
|
322
376
|
if cost > limit:
|
|
323
377
|
system_console.print(
|
|
324
|
-
f"\nCost limit exceeded. Current cost: {
|
|
378
|
+
f"\nCost limit exceeded. Current cost: {config.cost_unit}{cost:.4f}, "
|
|
379
|
+
f"input tokens: {input_toks}"
|
|
380
|
+
f"output tokens: {output_toks}"
|
|
325
381
|
)
|
|
326
382
|
break
|
|
383
|
+
else:
|
|
384
|
+
system_console.print(
|
|
385
|
+
f"\nTotal cost: {config.cost_unit}{cost:.4f}, input tokens: {input_toks}, output tokens: {output_toks}"
|
|
386
|
+
)
|
|
327
387
|
|
|
328
388
|
if not waiting_for_assistant:
|
|
329
389
|
if first_message:
|
|
@@ -335,13 +395,8 @@ Saves provided description and file contents of all the relevant file paths or g
|
|
|
335
395
|
history.append(parse_user_message_special(msg))
|
|
336
396
|
else:
|
|
337
397
|
waiting_for_assistant = False
|
|
338
|
-
|
|
339
|
-
cost_, input_toks_ = 0, 0
|
|
340
|
-
cost += cost_
|
|
341
|
-
input_toks += input_toks_
|
|
342
|
-
|
|
343
398
|
stream = client.messages.stream(
|
|
344
|
-
model=
|
|
399
|
+
model=config.model,
|
|
345
400
|
messages=history,
|
|
346
401
|
tools=tools,
|
|
347
402
|
max_tokens=8096,
|
|
@@ -361,7 +416,24 @@ Saves provided description and file contents of all the relevant file paths or g
|
|
|
361
416
|
with stream as stream_:
|
|
362
417
|
for chunk in stream_:
|
|
363
418
|
type_ = chunk.type
|
|
364
|
-
if type_
|
|
419
|
+
if type_ == "message_start":
|
|
420
|
+
message_start = chunk.message
|
|
421
|
+
# Update cost based on token usage from the API response
|
|
422
|
+
input_tokens = message_start.usage.input_tokens
|
|
423
|
+
input_toks += input_tokens
|
|
424
|
+
cost += (
|
|
425
|
+
input_tokens
|
|
426
|
+
* config.cost_file[config.model].cost_per_1m_input_tokens
|
|
427
|
+
) / 1_000_000
|
|
428
|
+
elif type_ == "message_stop":
|
|
429
|
+
message_stop = chunk.message
|
|
430
|
+
# Update cost based on output tokens
|
|
431
|
+
output_tokens = message_stop.usage.output_tokens
|
|
432
|
+
output_toks += output_tokens
|
|
433
|
+
cost += (
|
|
434
|
+
output_tokens
|
|
435
|
+
* config.cost_file[config.model].cost_per_1m_output_tokens
|
|
436
|
+
) / 1_000_000
|
|
365
437
|
continue
|
|
366
438
|
elif type_ == "content_block_start" and hasattr(
|
|
367
439
|
chunk, "content_block"
|
|
@@ -248,3 +248,78 @@ class TestInitialize(unittest.TestCase):
|
|
|
248
248
|
|
|
249
249
|
# Verify task memory was still loaded despite state error
|
|
250
250
|
self.assertIn("Following is the retrieved task:\ntest_memory", result)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def test_workspace_path_is_file(self):
|
|
254
|
+
"""Test initialize when workspace path points to a file"""
|
|
255
|
+
# Create a test file
|
|
256
|
+
test_file = os.path.join(self.test_workspace, "test.py")
|
|
257
|
+
os.makedirs(os.path.dirname(test_file), exist_ok=True)
|
|
258
|
+
with open(test_file, "w") as f:
|
|
259
|
+
f.write("print('test')")
|
|
260
|
+
|
|
261
|
+
with (
|
|
262
|
+
patch("os.path.exists") as mock_exists,
|
|
263
|
+
patch("os.path.isfile") as mock_isfile,
|
|
264
|
+
patch("wcgw.client.tools.get_repo_context") as mock_get_context,
|
|
265
|
+
patch("wcgw.client.tools.read_files") as mock_read_files,
|
|
266
|
+
):
|
|
267
|
+
mock_exists.return_value = True
|
|
268
|
+
mock_isfile.return_value = True
|
|
269
|
+
mock_get_context.return_value = (self.repo_context, os.path.dirname(test_file))
|
|
270
|
+
mock_read_files.return_value = f"``` {test_file}print('test')```"
|
|
271
|
+
|
|
272
|
+
# Call initialize with file path and no read_files_
|
|
273
|
+
result = initialize(
|
|
274
|
+
any_workspace_path=test_file,
|
|
275
|
+
read_files_=[],
|
|
276
|
+
task_id_to_resume="",
|
|
277
|
+
max_tokens=None,
|
|
278
|
+
mode=Modes.wcgw,
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
# Verify read_files was called with the file path
|
|
282
|
+
mock_read_files.assert_called_once_with([test_file], None)
|
|
283
|
+
|
|
284
|
+
# Verify repo context uses parent directory
|
|
285
|
+
mock_get_context.assert_called_once_with(os.path.dirname(test_file), 200)
|
|
286
|
+
|
|
287
|
+
# Verify file content is in output
|
|
288
|
+
self.assertIn(f"``` {test_file}print('test')", result)
|
|
289
|
+
|
|
290
|
+
# Verify cwd
|
|
291
|
+
self.assertIn(f"Initialized in directory (also cwd): {os.path.dirname(test_file)}\n", result)
|
|
292
|
+
|
|
293
|
+
def test_workspace_path_is_file_with_read_files(self):
|
|
294
|
+
"""Test initialize when workspace path points to a file and read_files_ is provided"""
|
|
295
|
+
test_file = os.path.join(self.test_workspace, "test.py")
|
|
296
|
+
extra_file = os.path.join(self.test_workspace, "extra.py")
|
|
297
|
+
|
|
298
|
+
with (
|
|
299
|
+
patch("os.path.exists") as mock_exists,
|
|
300
|
+
patch("os.path.isfile") as mock_isfile,
|
|
301
|
+
patch("wcgw.client.tools.get_repo_context") as mock_get_context,
|
|
302
|
+
patch("wcgw.client.tools.read_files") as mock_read_files,
|
|
303
|
+
):
|
|
304
|
+
mock_exists.return_value = True
|
|
305
|
+
mock_isfile.return_value = True
|
|
306
|
+
mock_get_context.return_value = (self.repo_context, os.path.dirname(test_file))
|
|
307
|
+
mock_read_files.return_value = f"``` {extra_file}extra content```"
|
|
308
|
+
|
|
309
|
+
# Call initialize with file path and explicit read_files_
|
|
310
|
+
result = initialize(
|
|
311
|
+
any_workspace_path=test_file,
|
|
312
|
+
read_files_=[extra_file],
|
|
313
|
+
task_id_to_resume="",
|
|
314
|
+
max_tokens=None,
|
|
315
|
+
mode=Modes.wcgw,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
# Verify read_files was called with the provided read_files_ only
|
|
319
|
+
mock_read_files.assert_called_once_with([extra_file], None)
|
|
320
|
+
|
|
321
|
+
# Verify repo context uses parent directory
|
|
322
|
+
mock_get_context.assert_called_once_with(os.path.dirname(test_file), 200)
|
|
323
|
+
|
|
324
|
+
# Verify extra file content is in output
|
|
325
|
+
self.assertIn(f"``` {extra_file}extra content", result)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-resource/.python-version
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-tool/mcp_simple_tool/__init__.py
RENAMED
|
File without changes
|
{wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-tool/mcp_simple_tool/__main__.py
RENAMED
|
File without changes
|
{wcgw-2.8.7 → wcgw-2.8.9}/src/mcp_wcgw_fork/examples/servers/simple-tool/mcp_simple_tool/server.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|