wcgw 5.3.2__tar.gz → 5.4.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.
- {wcgw-5.3.2 → wcgw-5.4.1}/Dockerfile +3 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/PKG-INFO +1 -1
- {wcgw-5.3.2 → wcgw-5.4.1}/pyproject.toml +1 -1
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/bash_state/bash_state.py +1 -1
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/diff-instructions.txt +1 -2
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/mcp_server/server.py +13 -2
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/tools.py +1 -11
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/types_.py +37 -1
- {wcgw-5.3.2 → wcgw-5.4.1}/tests/test_mcp_server.py +9 -7
- {wcgw-5.3.2 → wcgw-5.4.1}/uv.lock +1 -1
- {wcgw-5.3.2 → wcgw-5.4.1}/.github/workflows/python-publish.yml +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/.github/workflows/python-tests.yml +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/.github/workflows/python-types.yml +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/.gitignore +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/.gitmodules +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/.python-version +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/.vscode/settings.json +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/CLAUDE.md +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/LICENSE +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/README.md +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/__init__.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/__init__.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/bash_state/parser/__init__.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/bash_state/parser/bash_statement_parser.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/common.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/encoder/__init__.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/file_ops/diff_edit.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/file_ops/extensions.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/file_ops/search_replace.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/mcp_server/Readme.md +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/mcp_server/__init__.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/memory.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/modes.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/repo_ops/display_tree.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/repo_ops/file_stats.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/repo_ops/path_prob.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/repo_ops/paths_model.vocab +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/repo_ops/paths_tokens.model +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/repo_ops/repo_context.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/client/tool_prompts.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw/py.typed +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw_cli/__init__.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw_cli/__main__.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw_cli/anthropic_client.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw_cli/cli.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw_cli/openai_client.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/src/wcgw_cli/openai_utils.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/static/claude-ss.jpg +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/static/computer-use.jpg +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/static/example.jpg +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/static/rocket-icon.png +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/static/ss1.png +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/static/workflow-demo.gif +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/tests/test_bash_parser.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/tests/test_bash_parser_complex.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/tests/test_edit.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/tests/test_file_range_tracking.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/tests/test_readfiles.py +0 -0
- {wcgw-5.3.2 → wcgw-5.4.1}/tests/test_tools.py +0 -0
|
@@ -35,6 +35,9 @@ FROM python:3.12-slim-bookworm
|
|
|
35
35
|
|
|
36
36
|
RUN apt-get update && apt-get install -y screen && rm -rf /var/lib/apt/lists/*
|
|
37
37
|
|
|
38
|
+
# Create app user and group
|
|
39
|
+
RUN groupadd -r app && useradd -r -g app app
|
|
40
|
+
|
|
38
41
|
# Set the working directory in the container
|
|
39
42
|
WORKDIR /workspace
|
|
40
43
|
|
|
@@ -87,7 +87,7 @@ def check_if_screen_command_available() -> bool:
|
|
|
87
87
|
["which", "screen"], capture_output=True, check=True, timeout=0.2
|
|
88
88
|
)
|
|
89
89
|
return True
|
|
90
|
-
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
90
|
+
except (subprocess.CalledProcessError, FileNotFoundError, TimeoutError):
|
|
91
91
|
return False
|
|
92
92
|
|
|
93
93
|
|
|
@@ -61,8 +61,7 @@ def call_hello_renamed():
|
|
|
61
61
|
# *SEARCH/REPLACE block* Rules:
|
|
62
62
|
|
|
63
63
|
- Every "SEARCH" section must *EXACTLY MATCH* the existing file content, character for character, including all comments, docstrings, whitespaces, etc.
|
|
64
|
-
-
|
|
65
|
-
- An edit block can't edit over a previous edit in the same tool call.
|
|
64
|
+
- Use multiple search/replace blocks in a single FileWriteOrEdit tool call to edit in a single file in multiple places from top to bottom (separate calls are slower).
|
|
66
65
|
- Including multiple unique *SEARCH/REPLACE* blocks if needed.
|
|
67
66
|
- Include enough and only enough lines in each SEARCH section to uniquely match each set of lines that need to change.
|
|
68
67
|
- Keep *SEARCH/REPLACE* blocks concise.
|
|
@@ -121,11 +121,18 @@ async def handle_call_tool(
|
|
|
121
121
|
for output_or_done in output_or_dones:
|
|
122
122
|
if isinstance(output_or_done, str):
|
|
123
123
|
if issubclass(tool_type, Initialize):
|
|
124
|
-
|
|
124
|
+
# Prepare the original hardcoded message
|
|
125
|
+
original_message = """
|
|
125
126
|
- Additional important note: as soon as you encounter "The user has chosen to disallow the tool call.", immediately stop doing everything and ask user for the reason.
|
|
126
127
|
|
|
127
128
|
Initialize call done.
|
|
128
129
|
"""
|
|
130
|
+
|
|
131
|
+
# If custom instructions exist, prepend them to the original message
|
|
132
|
+
if CUSTOM_INSTRUCTIONS:
|
|
133
|
+
output_or_done += f"\n{CUSTOM_INSTRUCTIONS}\n{original_message}"
|
|
134
|
+
else:
|
|
135
|
+
output_or_done += original_message
|
|
129
136
|
|
|
130
137
|
content.append(types.TextContent(type="text", text=output_or_done))
|
|
131
138
|
else:
|
|
@@ -141,12 +148,16 @@ Initialize call done.
|
|
|
141
148
|
|
|
142
149
|
|
|
143
150
|
BASH_STATE = None
|
|
151
|
+
CUSTOM_INSTRUCTIONS = None
|
|
144
152
|
|
|
145
153
|
|
|
146
154
|
async def main() -> None:
|
|
147
|
-
global BASH_STATE
|
|
155
|
+
global BASH_STATE, CUSTOM_INSTRUCTIONS
|
|
148
156
|
CONFIG.update(3, 55, 5)
|
|
149
157
|
version = str(importlib.metadata.version("wcgw"))
|
|
158
|
+
|
|
159
|
+
# Read custom instructions from environment variable
|
|
160
|
+
CUSTOM_INSTRUCTIONS = os.getenv("WCGW_SERVER_INSTRUCTIONS")
|
|
150
161
|
|
|
151
162
|
# starting_dir is inside tmp dir
|
|
152
163
|
tmp_dir = get_tmpdir()
|
|
@@ -58,8 +58,6 @@ from ..types_ import (
|
|
|
58
58
|
from .encoder import EncoderDecoder, get_default_encoder
|
|
59
59
|
from .file_ops.extensions import select_max_tokens
|
|
60
60
|
from .file_ops.search_replace import (
|
|
61
|
-
DIVIDER_MARKER,
|
|
62
|
-
REPLACE_MARKER,
|
|
63
61
|
SEARCH_MARKER,
|
|
64
62
|
search_replace_edit,
|
|
65
63
|
)
|
|
@@ -819,16 +817,8 @@ def _is_edit(content: str, percentage: int) -> bool:
|
|
|
819
817
|
if not lines:
|
|
820
818
|
return False
|
|
821
819
|
line = lines[0]
|
|
822
|
-
if SEARCH_MARKER.match(line):
|
|
820
|
+
if SEARCH_MARKER.match(line) or (0 < percentage <= 50):
|
|
823
821
|
return True
|
|
824
|
-
if percentage <= 50:
|
|
825
|
-
for line in lines:
|
|
826
|
-
if (
|
|
827
|
-
SEARCH_MARKER.match(line)
|
|
828
|
-
or DIVIDER_MARKER.match(line)
|
|
829
|
-
or REPLACE_MARKER.match(line)
|
|
830
|
-
):
|
|
831
|
-
return True
|
|
832
822
|
return False
|
|
833
823
|
|
|
834
824
|
|
|
@@ -83,14 +83,17 @@ class Initialize(BaseModel):
|
|
|
83
83
|
|
|
84
84
|
class Command(BaseModel):
|
|
85
85
|
command: str
|
|
86
|
+
type: Literal["command"] = "command"
|
|
86
87
|
|
|
87
88
|
|
|
88
89
|
class StatusCheck(BaseModel):
|
|
89
|
-
status_check: Literal[True]
|
|
90
|
+
status_check: Literal[True] = True
|
|
91
|
+
type: Literal["status_check"] = "status_check"
|
|
90
92
|
|
|
91
93
|
|
|
92
94
|
class SendText(BaseModel):
|
|
93
95
|
send_text: str
|
|
96
|
+
type: Literal["send_text"] = "send_text"
|
|
94
97
|
|
|
95
98
|
|
|
96
99
|
Specials = Literal[
|
|
@@ -100,10 +103,39 @@ Specials = Literal[
|
|
|
100
103
|
|
|
101
104
|
class SendSpecials(BaseModel):
|
|
102
105
|
send_specials: Sequence[Specials]
|
|
106
|
+
type: Literal["send_specials"] = "send_specials"
|
|
103
107
|
|
|
104
108
|
|
|
105
109
|
class SendAscii(BaseModel):
|
|
106
110
|
send_ascii: Sequence[int]
|
|
111
|
+
type: Literal["send_ascii"] = "send_ascii"
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class ActionJsonSchema(BaseModel):
|
|
115
|
+
type: Literal[
|
|
116
|
+
"command", "status_check", "send_text", "send_specials", "send_ascii"
|
|
117
|
+
] = Field(description="type of action.")
|
|
118
|
+
command: Optional[str] = Field(
|
|
119
|
+
default=None, description='Set only if type="command"'
|
|
120
|
+
)
|
|
121
|
+
status_check: Optional[Literal[True]] = Field(
|
|
122
|
+
default=None, description='Set only if type="status_check"'
|
|
123
|
+
)
|
|
124
|
+
send_text: Optional[str] = Field(
|
|
125
|
+
default=None, description='Set only if type="send_text"'
|
|
126
|
+
)
|
|
127
|
+
send_specials: Optional[Sequence[Specials]] = Field(
|
|
128
|
+
default=None, description='Set only if type="send_specials"'
|
|
129
|
+
)
|
|
130
|
+
send_ascii: Optional[Sequence[int]] = Field(
|
|
131
|
+
default=None, description='Set only if type="send_ascii"'
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class BashCommandOverride(BaseModel):
|
|
136
|
+
action_json: ActionJsonSchema
|
|
137
|
+
wait_for_seconds: Optional[float] = None
|
|
138
|
+
thread_id: str
|
|
107
139
|
|
|
108
140
|
|
|
109
141
|
class BashCommand(BaseModel):
|
|
@@ -111,6 +143,10 @@ class BashCommand(BaseModel):
|
|
|
111
143
|
wait_for_seconds: Optional[float] = None
|
|
112
144
|
thread_id: str
|
|
113
145
|
|
|
146
|
+
@staticmethod
|
|
147
|
+
def model_json_schema(*args, **kwargs) -> dict[str, Any]: # type: ignore
|
|
148
|
+
return BashCommandOverride.model_json_schema(*args, **kwargs)
|
|
149
|
+
|
|
114
150
|
|
|
115
151
|
class ReadImage(BaseModel):
|
|
116
152
|
file_path: str
|
|
@@ -142,14 +142,16 @@ async def test_handle_list_tools():
|
|
|
142
142
|
assert "action_json" in properties
|
|
143
143
|
assert "wait_for_seconds" in properties
|
|
144
144
|
# Check type field has all the command types
|
|
145
|
-
type_properties =
|
|
146
|
-
|
|
145
|
+
type_properties = tool.inputSchema["$defs"]["ActionJsonSchema"][
|
|
146
|
+
"properties"
|
|
147
|
+
]
|
|
148
|
+
type_refs = set(type_properties)
|
|
147
149
|
required_types = {
|
|
148
|
-
"
|
|
149
|
-
"
|
|
150
|
-
"
|
|
151
|
-
"
|
|
152
|
-
"
|
|
150
|
+
"command",
|
|
151
|
+
"status_check",
|
|
152
|
+
"send_text",
|
|
153
|
+
"send_specials",
|
|
154
|
+
"send_ascii",
|
|
153
155
|
}
|
|
154
156
|
assert required_types.issubset(type_refs)
|
|
155
157
|
elif tool.name == "FileWriteOrEdit":
|
|
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
|