bingocode 1.0.40 → 1.1.42

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 (63) hide show
  1. package/bin/bingo-win.cjs +2 -1
  2. package/bin/bingocode-win.cjs +2 -1
  3. package/bin/claude-win.cjs +2 -1
  4. package/bun.lock +1716 -0
  5. package/package.json +14 -2
  6. package/src/server/config/providers.yaml +1 -1
  7. package/src/server/proxy/transform/anthropicToOpenaiChat.ts +23 -9
  8. package/adapters/README.md +0 -87
  9. package/adapters/common/__tests__/chat-queue.test.ts +0 -61
  10. package/adapters/common/__tests__/format.test.ts +0 -148
  11. package/adapters/common/__tests__/http-client.test.ts +0 -105
  12. package/adapters/common/__tests__/message-buffer.test.ts +0 -84
  13. package/adapters/common/__tests__/message-dedup.test.ts +0 -57
  14. package/adapters/common/__tests__/session-store.test.ts +0 -62
  15. package/adapters/common/__tests__/ws-bridge.test.ts +0 -177
  16. package/adapters/common/attachment/__tests__/attachment-limits.test.ts +0 -52
  17. package/adapters/common/attachment/__tests__/attachment-store.test.ts +0 -108
  18. package/adapters/common/attachment/__tests__/image-block-watcher.test.ts +0 -115
  19. package/adapters/common/attachment/attachment-limits.ts +0 -58
  20. package/adapters/common/attachment/attachment-store.ts +0 -121
  21. package/adapters/common/attachment/attachment-types.ts +0 -29
  22. package/adapters/common/attachment/image-block-watcher.ts +0 -94
  23. package/adapters/common/chat-queue.ts +0 -24
  24. package/adapters/common/config.ts +0 -96
  25. package/adapters/common/format.ts +0 -229
  26. package/adapters/common/http-client.ts +0 -107
  27. package/adapters/common/message-buffer.ts +0 -91
  28. package/adapters/common/message-dedup.ts +0 -57
  29. package/adapters/common/pairing.ts +0 -149
  30. package/adapters/common/session-store.ts +0 -60
  31. package/adapters/common/ws-bridge.ts +0 -282
  32. package/adapters/feishu/__tests__/card-errors.test.ts +0 -194
  33. package/adapters/feishu/__tests__/cardkit.test.ts +0 -295
  34. package/adapters/feishu/__tests__/extract-payload.test.ts +0 -77
  35. package/adapters/feishu/__tests__/feishu.test.ts +0 -907
  36. package/adapters/feishu/__tests__/flush-controller.test.ts +0 -290
  37. package/adapters/feishu/__tests__/markdown-style.test.ts +0 -353
  38. package/adapters/feishu/__tests__/media.test.ts +0 -120
  39. package/adapters/feishu/__tests__/streaming-card.test.ts +0 -914
  40. package/adapters/feishu/card-errors.ts +0 -151
  41. package/adapters/feishu/cardkit.ts +0 -294
  42. package/adapters/feishu/extract-payload.ts +0 -95
  43. package/adapters/feishu/flush-controller.ts +0 -149
  44. package/adapters/feishu/index.ts +0 -1275
  45. package/adapters/feishu/markdown-style.ts +0 -212
  46. package/adapters/feishu/media.ts +0 -176
  47. package/adapters/feishu/streaming-card.ts +0 -612
  48. package/adapters/package.json +0 -23
  49. package/adapters/telegram/__tests__/media.test.ts +0 -86
  50. package/adapters/telegram/__tests__/telegram.test.ts +0 -115
  51. package/adapters/telegram/index.ts +0 -754
  52. package/adapters/telegram/media.ts +0 -89
  53. package/adapters/tsconfig.json +0 -18
  54. package/runtime/mac_helper.py +0 -775
  55. package/runtime/requirements-win.txt +0 -7
  56. package/runtime/requirements.txt +0 -6
  57. package/runtime/test_helpers.py +0 -322
  58. package/runtime/win_helper.py +0 -723
  59. package/scripts/count-app-loc.ts +0 -256
  60. package/scripts/release.ts +0 -130
  61. package/start-cli.bat +0 -7
  62. package/stubs/ant-claude-for-chrome-mcp.ts +0 -24
  63. package/stubs/color-diff-napi.ts +0 -45
@@ -1,7 +0,0 @@
1
- mss>=10.1.0
2
- Pillow>=11.3.0
3
- pyautogui>=0.9.54
4
- pywin32>=306
5
- psutil>=5.9.0
6
- pyperclip>=1.8.2
7
- screeninfo>=0.8.1
@@ -1,6 +0,0 @@
1
- mss>=10.1.0
2
- Pillow>=11.3.0
3
- pyautogui>=0.9.54
4
- pyobjc-core>=11.1
5
- pyobjc-framework-Cocoa>=11.1
6
- pyobjc-framework-Quartz>=11.1
@@ -1,322 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Cross-platform tests for mac_helper.py and win_helper.py.
3
-
4
- Tests the platform-independent parts (JSON protocol, key mapping, capture logic)
5
- without requiring platform-specific dependencies. Can run on any OS with pytest.
6
-
7
- Usage:
8
- python -m pytest runtime/test_helpers.py -v
9
- # or simply:
10
- python runtime/test_helpers.py
11
- """
12
- from __future__ import annotations
13
-
14
- import json
15
- import subprocess
16
- import sys
17
- import unittest
18
- from pathlib import Path
19
- from unittest.mock import patch, MagicMock
20
-
21
- # Determine which helper to test based on current platform
22
- IS_WINDOWS = sys.platform == "win32"
23
- IS_MACOS = sys.platform == "darwin"
24
-
25
- RUNTIME_DIR = Path(__file__).parent
26
- MAC_HELPER = RUNTIME_DIR / "mac_helper.py"
27
- WIN_HELPER = RUNTIME_DIR / "win_helper.py"
28
-
29
-
30
- class TestKeyMap(unittest.TestCase):
31
- """Test the KEY_MAP and normalize_key function — platform-independent logic."""
32
-
33
- def _load_key_map(self, helper_path: Path) -> dict[str, str]:
34
- """Extract KEY_MAP from a helper by importing it with mocked deps."""
35
- # Read the file and extract just the KEY_MAP dict
36
- source = helper_path.read_text()
37
- # Find KEY_MAP definition
38
- start = source.index("KEY_MAP = {")
39
- # Find the matching closing brace
40
- depth = 0
41
- for i, ch in enumerate(source[start:], start):
42
- if ch == "{":
43
- depth += 1
44
- elif ch == "}":
45
- depth -= 1
46
- if depth == 0:
47
- end = i + 1
48
- break
49
- key_map_source = source[start:end]
50
- ns: dict = {}
51
- exec(key_map_source, ns)
52
- return ns["KEY_MAP"]
53
-
54
- def test_mac_key_map_exists(self):
55
- if not MAC_HELPER.exists():
56
- self.skipTest("mac_helper.py not found")
57
- km = self._load_key_map(MAC_HELPER)
58
- self.assertIn("cmd", km)
59
- self.assertIn("ctrl", km)
60
- self.assertEqual(km["cmd"], "command")
61
- self.assertEqual(km["alt"], "option")
62
-
63
- def test_win_key_map_exists(self):
64
- if not WIN_HELPER.exists():
65
- self.skipTest("win_helper.py not found")
66
- km = self._load_key_map(WIN_HELPER)
67
- self.assertIn("cmd", km)
68
- self.assertIn("ctrl", km)
69
- # Windows maps cmd/command/meta to 'win' key
70
- self.assertEqual(km["cmd"], "win")
71
- self.assertEqual(km["command"], "win")
72
- self.assertEqual(km["meta"], "win")
73
- # Windows maps alt/option to 'alt'
74
- self.assertEqual(km["alt"], "alt")
75
- self.assertEqual(km["option"], "alt")
76
-
77
- def test_common_keys_present_in_both(self):
78
- """Both helpers must have the same set of key names."""
79
- if not MAC_HELPER.exists() or not WIN_HELPER.exists():
80
- self.skipTest("Both helpers required")
81
- mac_km = self._load_key_map(MAC_HELPER)
82
- win_km = self._load_key_map(WIN_HELPER)
83
- # All keys in mac should be in win and vice versa
84
- self.assertEqual(set(mac_km.keys()), set(win_km.keys()),
85
- "KEY_MAP keys must be identical across platforms")
86
-
87
- def test_all_alphabet_keys(self):
88
- """All a-z keys should map to themselves."""
89
- for helper in [MAC_HELPER, WIN_HELPER]:
90
- if not helper.exists():
91
- continue
92
- km = self._load_key_map(helper)
93
- for char in "abcdefghijklmnopqrstuvwxyz":
94
- self.assertEqual(km[char], char, f"{helper.name}: {char} should map to itself")
95
-
96
- def test_all_digit_keys(self):
97
- """All 0-9 keys should map to themselves."""
98
- for helper in [MAC_HELPER, WIN_HELPER]:
99
- if not helper.exists():
100
- continue
101
- km = self._load_key_map(helper)
102
- for digit in "0123456789":
103
- self.assertEqual(km[digit], digit, f"{helper.name}: {digit} should map to itself")
104
-
105
- def test_function_keys(self):
106
- """F1-F12 should map to themselves."""
107
- for helper in [MAC_HELPER, WIN_HELPER]:
108
- if not helper.exists():
109
- continue
110
- km = self._load_key_map(helper)
111
- for i in range(1, 13):
112
- key = f"f{i}"
113
- self.assertEqual(km[key], key, f"{helper.name}: {key} should map to itself")
114
-
115
-
116
- class TestJSONProtocol(unittest.TestCase):
117
- """Test that both helpers follow the same JSON command protocol."""
118
-
119
- def _get_helper(self) -> Path:
120
- """Get the appropriate helper for the current platform."""
121
- if IS_WINDOWS and WIN_HELPER.exists():
122
- return WIN_HELPER
123
- if IS_MACOS and MAC_HELPER.exists():
124
- return MAC_HELPER
125
- return MAC_HELPER if MAC_HELPER.exists() else WIN_HELPER
126
-
127
- def _parse_main_commands(self, helper_path: Path) -> list[str]:
128
- """Extract all command names from the main() dispatcher."""
129
- source = helper_path.read_text()
130
- commands = []
131
- for line in source.splitlines():
132
- stripped = line.strip()
133
- if stripped.startswith('if command == "'):
134
- cmd = stripped.split('"')[1]
135
- commands.append(cmd)
136
- return commands
137
-
138
- def test_both_helpers_same_commands(self):
139
- """Both helpers must support the exact same set of commands."""
140
- if not MAC_HELPER.exists() or not WIN_HELPER.exists():
141
- self.skipTest("Both helpers required")
142
- mac_cmds = set(self._parse_main_commands(MAC_HELPER))
143
- win_cmds = set(self._parse_main_commands(WIN_HELPER))
144
- self.assertEqual(mac_cmds, win_cmds,
145
- f"Command sets differ.\nOnly in mac: {mac_cmds - win_cmds}\nOnly in win: {win_cmds - mac_cmds}")
146
-
147
- def test_expected_commands_exist(self):
148
- """Core commands should be present in each helper."""
149
- expected = {
150
- "check_permissions", "list_displays", "get_display_size",
151
- "screenshot", "resolve_prepare_capture", "zoom",
152
- "prepare_for_action", "preview_hide_set", "find_window_displays",
153
- "key", "hold_key", "type", "click", "drag",
154
- "move_mouse", "scroll", "mouse_down", "mouse_up",
155
- "cursor_position", "frontmost_app", "app_under_point",
156
- "list_installed_apps", "list_running_apps", "open_app",
157
- "read_clipboard", "write_clipboard", "paste_clipboard",
158
- }
159
- for helper in [MAC_HELPER, WIN_HELPER]:
160
- if not helper.exists():
161
- continue
162
- cmds = set(self._parse_main_commands(helper))
163
- missing = expected - cmds
164
- self.assertFalse(missing,
165
- f"{helper.name} missing commands: {missing}")
166
-
167
- def test_unknown_command_returns_error(self):
168
- """Running a non-existent command should return a JSON error."""
169
- helper = self._get_helper()
170
- if not helper.exists():
171
- self.skipTest("No helper found")
172
- # On macOS without venv, mac_helper.py may fail at import (AppKit);
173
- # on Windows without venv, win_helper.py may fail at import (win32gui).
174
- # Only test if the helper can actually import.
175
- check = subprocess.run(
176
- [sys.executable, "-c", f"import importlib.util; "
177
- f"spec = importlib.util.spec_from_file_location('h', '{helper}')"],
178
- capture_output=True, text=True
179
- )
180
- result = subprocess.run(
181
- [sys.executable, str(helper), "nonexistent_command_xyz"],
182
- capture_output=True, text=True
183
- )
184
- if result.returncode == 1 and not result.stdout.strip():
185
- # Import failed — platform deps missing, skip this test
186
- self.skipTest(f"Cannot run {helper.name} on this platform (missing deps)")
187
- # Should exit with code 2
188
- self.assertEqual(result.returncode, 2)
189
- parsed = json.loads(result.stdout.strip())
190
- self.assertFalse(parsed["ok"])
191
- self.assertEqual(parsed["error"]["code"], "bad_command")
192
-
193
-
194
- class TestHelperOutputFormat(unittest.TestCase):
195
- """Test the JSON output helpers are consistent."""
196
-
197
- def test_json_output_function_exists(self):
198
- """Both helpers should define json_output and error_output."""
199
- for helper in [MAC_HELPER, WIN_HELPER]:
200
- if not helper.exists():
201
- continue
202
- source = helper.read_text()
203
- self.assertIn("def json_output(", source,
204
- f"{helper.name} missing json_output function")
205
- self.assertIn("def error_output(", source,
206
- f"{helper.name} missing error_output function")
207
-
208
- def test_main_entry_point(self):
209
- """Both helpers should have the standard main entry point."""
210
- for helper in [MAC_HELPER, WIN_HELPER]:
211
- if not helper.exists():
212
- continue
213
- source = helper.read_text()
214
- self.assertIn('if __name__ == "__main__":', source,
215
- f"{helper.name} missing __main__ guard")
216
- self.assertIn("def main()", source,
217
- f"{helper.name} missing main() function")
218
-
219
-
220
- class TestWinHelperPermissions(unittest.TestCase):
221
- """Windows-specific: permissions should always return True."""
222
-
223
- def test_check_permissions_always_granted(self):
224
- """On Windows, permissions are not needed — should always be True."""
225
- if not WIN_HELPER.exists():
226
- self.skipTest("win_helper.py not found")
227
-
228
- # Extract and exec just the check_permissions function
229
- source = WIN_HELPER.read_text()
230
-
231
- # Find the function
232
- self.assertIn("def check_permissions()", source)
233
-
234
- # The function should return both as True
235
- # We can verify by reading the source
236
- start = source.index("def check_permissions()")
237
- # Find next def or end
238
- rest = source[start:]
239
- lines = rest.split("\n")
240
- func_lines = [lines[0]]
241
- for line in lines[1:]:
242
- if line and not line[0].isspace() and not line.startswith("#"):
243
- break
244
- func_lines.append(line)
245
- func_source = "\n".join(func_lines)
246
- self.assertIn('"accessibility": True', func_source)
247
- self.assertIn('"screenRecording": True', func_source)
248
-
249
-
250
- class TestMacHelperPermissions(unittest.TestCase):
251
- """macOS helper permission detection should use the official trust API."""
252
-
253
- def test_check_permissions_uses_ax_api_instead_of_system_events(self):
254
- if not MAC_HELPER.exists():
255
- self.skipTest("mac_helper.py not found")
256
-
257
- source = MAC_HELPER.read_text()
258
-
259
- self.assertIn("def detect_accessibility_permission()", source)
260
- self.assertIn("AXIsProcessTrusted", source)
261
-
262
- start = source.index("def check_permissions()")
263
- rest = source[start:]
264
- lines = rest.split("\n")
265
- func_lines = [lines[0]]
266
- for line in lines[1:]:
267
- if line and not line[0].isspace() and not line.startswith("#"):
268
- break
269
- func_lines.append(line)
270
- func_source = "\n".join(func_lines)
271
-
272
- self.assertIn("detect_accessibility_permission()", func_source)
273
- self.assertNotIn('tell application "System Events"', func_source)
274
-
275
- def test_clipboard_shortcuts_use_osascript_path(self):
276
- if not MAC_HELPER.exists():
277
- self.skipTest("mac_helper.py not found")
278
-
279
- source = MAC_HELPER.read_text()
280
- self.assertIn("def paste_clipboard()", source)
281
- self.assertIn('send_keystroke_via_osascript("v", ["command"])', source)
282
- self.assertIn('if parts == ["command", "v"]:', source)
283
- self.assertIn('elif parts == ["command", "a"]:', source)
284
-
285
-
286
- class TestCrossPlatformFunctions(unittest.TestCase):
287
- """Test functions that are identical between both helpers."""
288
-
289
- def _get_function_body(self, helper_path: Path, func_name: str) -> str:
290
- """Extract a function's body (code lines only, no comments/blanks)."""
291
- source = helper_path.read_text()
292
- marker = f"def {func_name}("
293
- if marker not in source:
294
- return ""
295
- start = source.index(marker)
296
- rest = source[start:]
297
- lines = rest.split("\n")
298
- func_lines = [lines[0]]
299
- for line in lines[1:]:
300
- # Stop at next top-level def/class or non-indented non-empty line
301
- stripped = line.strip()
302
- if line and not line[0].isspace() and stripped and not stripped.startswith("#"):
303
- break
304
- # Skip comments and blank lines for comparison
305
- if stripped.startswith("#") or not stripped:
306
- continue
307
- func_lines.append(line)
308
- return " ".join(" ".join(func_lines).split())
309
-
310
- def test_input_functions_identical(self):
311
- """Input action functions (click, scroll, etc.) should be identical."""
312
- if not MAC_HELPER.exists() or not WIN_HELPER.exists():
313
- self.skipTest("Both helpers required")
314
- for func in ["click", "scroll", "hold_keys", "type_text"]:
315
- mac_src = self._get_function_body(MAC_HELPER, func)
316
- win_src = self._get_function_body(WIN_HELPER, func)
317
- self.assertEqual(mac_src, win_src,
318
- f"{func} should be identical across platforms")
319
-
320
-
321
- if __name__ == "__main__":
322
- unittest.main()