wcgw 1.5.0__py3-none-any.whl → 1.5.1__py3-none-any.whl

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.

@@ -26,7 +26,6 @@ from ..types_ import (
26
26
  OUTPUT_DIR = "/tmp/outputs"
27
27
  TYPING_DELAY_MS = 12
28
28
  TYPING_GROUP_SIZE = 50
29
- TRUNCATED_MESSAGE: str = "<response clipped><NOTE>To save on context only part of this file has been shown to you.</NOTE>"
30
29
 
31
30
  Action = Literal[
32
31
  "key",
@@ -2,23 +2,22 @@
2
2
 
3
3
  ## Setup
4
4
 
5
- Install xdtool
6
-
7
- ```sh
8
- brew install xdotool
9
-
10
- # On macos:
11
- defaults write org.x.X11 enable_test_extensions -boolean true
12
- ```
13
-
14
5
  Update `claude_desktop_config.json` (~/Library/Application Support/Claude/claude_desktop_config.json)
15
6
 
16
7
  ```json
17
8
  {
18
9
  "mcpServers": {
19
10
  "wcgw": {
20
- "command": "uvx",
21
- "args": ["--from", "wcgw@latest", "wcgw_mcp"]
11
+ "command": "uv",
12
+ "args": [
13
+ "tool",
14
+ "run",
15
+ "--from",
16
+ "wcgw@latest",
17
+ "--python",
18
+ "3.12",
19
+ "wcgw_mcp"
20
+ ]
22
21
  }
23
22
  }
24
23
  }
@@ -26,9 +25,9 @@ Update `claude_desktop_config.json` (~/Library/Application Support/Claude/claude
26
25
 
27
26
  Then restart claude app.
28
27
 
29
- ### Computer use support using desktop on docker
28
+ ### [Optional] Computer use support using desktop on docker
30
29
 
31
- Controlling the system isn't possible yet, but you can connect to a docker container which runs a linux os with desktop.
30
+ Computer use is enabled by default. Claude will be able to connect to any docker container with linux environment. Native system control isn't supported outside docker.
32
31
 
33
32
  First run a sample docker image with desktop and optionally VNC connection:
34
33
 
@@ -47,7 +46,7 @@ docker run \
47
46
  tail -f /dev/null"
48
47
  ```
49
48
 
50
- Connect to `http://localhost:6080/vnc.html` for desktop view (VNC) of the system running in the docker.
49
+ Connect to `http://localhost:6080/vnc.html` for desktop view (VNC) of the system running in the docker. Then ask claude to control the docker os.
51
50
 
52
51
  ## Usage
53
52
 
@@ -10,8 +10,9 @@ from mcp.server.models import InitializationOptions
10
10
  import mcp.types as types
11
11
  from mcp.types import Tool as ToolParam
12
12
  from mcp.server import NotificationOptions, Server
13
- from pydantic import AnyUrl, ValidationError
13
+ from pydantic import AnyUrl, BaseModel, ValidationError
14
14
  import mcp.server.stdio
15
+ from .. import tools
15
16
  from ..tools import DoneFlag, get_tool_output, which_tool_name, default_enc
16
17
  from ...types_ import (
17
18
  BashCommand,
@@ -29,6 +30,7 @@ from ...types_ import (
29
30
  )
30
31
  from ..computer_use import Computer
31
32
 
33
+ tools.TIMEOUT = 3
32
34
 
33
35
  server = Server("wcgw")
34
36
 
@@ -272,7 +274,7 @@ async def main() -> None:
272
274
  experimental_capabilities={},
273
275
  ),
274
276
  ),
275
- raise_exceptions=True,
277
+ raise_exceptions=False,
276
278
  )
277
279
  except BaseException as e:
278
280
  print(f"Server encountered an error: {e}", file=sys.stderr)
wcgw/client/sys_utils.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import subprocess
2
2
 
3
3
  MAX_RESPONSE_LEN: int = 16000
4
+ TRUNCATED_MESSAGE: str = "<response clipped><NOTE>To save on context only part of this file has been shown to you.</NOTE>"
4
5
 
5
6
 
6
7
  def maybe_truncate(content: str, truncate_after: int | None = MAX_RESPONSE_LEN) -> str:
@@ -14,7 +15,7 @@ def maybe_truncate(content: str, truncate_after: int | None = MAX_RESPONSE_LEN)
14
15
 
15
16
  def command_run(
16
17
  cmd: str,
17
- timeout: float | None = 30.0, # seconds
18
+ timeout: float | None = 3.0, # seconds
18
19
  truncate_after: int | None = MAX_RESPONSE_LEN,
19
20
  text: bool = True,
20
21
  ) -> tuple[int, str, str]:
wcgw/client/tools.py CHANGED
@@ -71,7 +71,7 @@ from .openai_utils import get_input_cost, get_output_cost
71
71
 
72
72
  console = rich.console.Console(style="magenta", highlight=False, markup=False)
73
73
 
74
- TIMEOUT = 30
74
+ TIMEOUT = 5
75
75
 
76
76
 
77
77
  def render_terminal_output(text: str) -> str:
@@ -113,9 +113,9 @@ def start_shell() -> pexpect.spawn: # type: ignore
113
113
  encoding="utf-8",
114
114
  timeout=TIMEOUT,
115
115
  )
116
- SHELL.expect(PROMPT)
116
+ SHELL.expect(PROMPT, timeout=TIMEOUT)
117
117
  SHELL.sendline("stty -icanon -echo")
118
- SHELL.expect(PROMPT)
118
+ SHELL.expect(PROMPT, timeout=TIMEOUT)
119
119
  return SHELL
120
120
 
121
121
 
@@ -135,15 +135,15 @@ def _get_exit_code() -> int:
135
135
  return 0
136
136
  # First reset the prompt in case venv was sourced or other reasons.
137
137
  SHELL.sendline(f"export PS1={PROMPT}")
138
- SHELL.expect(PROMPT)
138
+ SHELL.expect(PROMPT, timeout=0.2)
139
139
  # Reset echo also if it was enabled
140
140
  SHELL.sendline("stty -icanon -echo")
141
- SHELL.expect(PROMPT)
141
+ SHELL.expect(PROMPT, timeout=0.2)
142
142
  SHELL.sendline("echo $?")
143
143
  before = ""
144
144
  while not _is_int(before): # Consume all previous output
145
145
  try:
146
- SHELL.expect(PROMPT)
146
+ SHELL.expect(PROMPT, timeout=0.2)
147
147
  except pexpect.TIMEOUT:
148
148
  print(f"Couldn't get exit code, before: {before}")
149
149
  raise
@@ -215,7 +215,7 @@ def update_repl_prompt(command: str) -> bool:
215
215
 
216
216
  def get_cwd() -> str:
217
217
  SHELL.sendline("pwd")
218
- SHELL.expect(PROMPT)
218
+ SHELL.expect(PROMPT, timeout=0.2)
219
219
  assert isinstance(SHELL.before, str)
220
220
  current_dir = render_terminal_output(SHELL.before).strip()
221
221
  return current_dir
@@ -342,13 +342,13 @@ def execute_bash(
342
342
  SHELL.expect(PROMPT)
343
343
  return "---\n\nFailure: user interrupted the execution", 0.0
344
344
 
345
- wait = timeout_s or 5
345
+ wait = timeout_s or TIMEOUT
346
346
  index = SHELL.expect([PROMPT, pexpect.TIMEOUT], timeout=wait)
347
347
  if index == 1:
348
348
  BASH_STATE = "pending"
349
349
  text = SHELL.before or ""
350
350
 
351
- text = render_terminal_output(text)
351
+ text = render_terminal_output(text[-100_000:])
352
352
  tokens = enc.encode(text)
353
353
 
354
354
  if max_tokens and len(tokens) >= max_tokens:
@@ -855,7 +855,7 @@ def get_tool_output(
855
855
  if imgBs64:
856
856
  console.print("Captured screenshot")
857
857
  outputs.append(ImageData(media_type="image/png", data=imgBs64))
858
- if not IS_IN_DOCKER:
858
+ if not IS_IN_DOCKER and isinstance(arg, GetScreenInfo):
859
859
  try:
860
860
  # At this point we should go into the docker env
861
861
  res, _ = execute_bash(
@@ -989,7 +989,7 @@ def read_file(readfile: ReadFile, max_tokens: Optional[int]) -> str:
989
989
 
990
990
  else:
991
991
  return_code, content, stderr = command_run(
992
- f"cat {readfile.file_path}",
992
+ f"cat {readfile.file_path}", timeout=TIMEOUT
993
993
  )
994
994
  if return_code != 0:
995
995
  raise Exception(
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: wcgw
3
- Version: 1.5.0
3
+ Version: 1.5.1
4
4
  Summary: What could go wrong giving full shell access to chatgpt?
5
5
  Project-URL: Homepage, https://github.com/rusiaaman/wcgw
6
6
  Author-email: Aman Rusia <gapypi@arcfu.com>
7
7
  Requires-Python: <3.13,>=3.11
8
8
  Requires-Dist: anthropic>=0.39.0
9
9
  Requires-Dist: fastapi>=0.115.0
10
- Requires-Dist: mcp>=1.0.0
10
+ Requires-Dist: mcp
11
11
  Requires-Dist: mypy>=1.11.2
12
12
  Requires-Dist: nltk>=3.9.1
13
13
  Requires-Dist: openai>=1.46.0
@@ -5,18 +5,18 @@ wcgw/client/__main__.py,sha256=wcCrL4PjG51r5wVKqJhcoJPTLfHW0wNbD31DrUN0MWI,28
5
5
  wcgw/client/anthropic_client.py,sha256=owR-nIxQVGgw_ned8JOQ-QmmCBQvZSqgD08kYpU_Rbg,17730
6
6
  wcgw/client/cli.py,sha256=Oja42CHkVO8puqOXflko9NeephYCMa85aBmQTEjBZtI,932
7
7
  wcgw/client/common.py,sha256=grH-yV_4tnTQZ29xExn4YicGLxEq98z-HkEZwH0ReSg,1410
8
- wcgw/client/computer_use.py,sha256=jZCw4p7qfHEmhv9eqc1zyPyLTUyb54Ipw5UnRqzRWqc,14399
8
+ wcgw/client/computer_use.py,sha256=hadmsHpwVRqTZh4Q7Ssu3xdnNLnBW4y-pd5P6D-qqKE,14276
9
9
  wcgw/client/diff-instructions.txt,sha256=s5AJKG23JsjwRYhFZFQVvwDpF67vElawrmdXwvukR1A,1683
10
10
  wcgw/client/openai_client.py,sha256=L61ajFVQW2QPS3C0n1YsjgF4vQKfMIZHmp6iFBHutX8,17748
11
11
  wcgw/client/openai_utils.py,sha256=YNwCsA-Wqq7jWrxP0rfQmBTb1dI0s7dWXzQqyTzOZT4,2629
12
- wcgw/client/sys_utils.py,sha256=7_7o1Au33OkZUsW5nKW55xW_YRYZlvUpY6tHVLIILm8,1254
13
- wcgw/client/tools.py,sha256=PbS1YBELqibShPrpKCGq3KeXLS4t6AhTTkB5pQMgX-g,32476
14
- wcgw/client/mcp_server/Readme.md,sha256=dK9NqFQ0_tblLOgPI6DjWrSYs2UWKEJkvgnLW3T-EZk,1944
12
+ wcgw/client/sys_utils.py,sha256=GajPntKhaTUMn6EOmopENWZNR2G_BJyuVbuot0x6veI,1376
13
+ wcgw/client/tools.py,sha256=Ce_1eLXl6W1U2EcNk2JPiCAKmEnTHt3Jd78ZHlW-ET4,32629
14
+ wcgw/client/mcp_server/Readme.md,sha256=mztipVTwqXLLenbVihnodq7gUF2Q0_YOKOMW3MiV3UM,2020
15
15
  wcgw/client/mcp_server/__init__.py,sha256=cQ7PUrEmXUpio8x0SEoGWP5hCRPd7z2bAkNCbYbtTys,236
16
- wcgw/client/mcp_server/server.py,sha256=EzO4VNuSfcIMTue3sCsCqTTMku_AmsgJctBuPQfEQ8w,10160
16
+ wcgw/client/mcp_server/server.py,sha256=niS5elM7vdu181DjDSNXRbipFjt9Ke-H9HQMWMwNnXg,10211
17
17
  wcgw/relay/serve.py,sha256=RUcUeyL4Xt0EEo12Ul6VQjb4tRle4uIdsa85v7XXxEw,8771
18
18
  wcgw/relay/static/privacy.txt,sha256=s9qBdbx2SexCpC_z33sg16TptmAwDEehMCLz4L50JLc,529
19
- wcgw-1.5.0.dist-info/METADATA,sha256=_bTBKk1cMtbqt7dgM-wge3LuNCTe4s1CDzdSyR7P3WU,6292
20
- wcgw-1.5.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
21
- wcgw-1.5.0.dist-info/entry_points.txt,sha256=eKo1omwbAggWlQ0l7GKoR7uV1-j16nk9tK0BhC2Oz_E,120
22
- wcgw-1.5.0.dist-info/RECORD,,
19
+ wcgw-1.5.1.dist-info/METADATA,sha256=ls5ebZhUUraGJqdSIHCggftaq16jnGJS8VxHMj1Y0GY,6285
20
+ wcgw-1.5.1.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
21
+ wcgw-1.5.1.dist-info/entry_points.txt,sha256=eKo1omwbAggWlQ0l7GKoR7uV1-j16nk9tK0BhC2Oz_E,120
22
+ wcgw-1.5.1.dist-info/RECORD,,
File without changes