witbitz-code 1.6.0__tar.gz → 1.6.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.
- {witbitz_code-1.6.0/src/witbitz_code.egg-info → witbitz_code-1.6.1}/PKG-INFO +1 -1
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/pyproject.toml +1 -1
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/__init__.py +1 -1
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/uninstall.py +72 -5
- {witbitz_code-1.6.0 → witbitz_code-1.6.1/src/witbitz_code.egg-info}/PKG-INFO +1 -1
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_uninstall.py +37 -1
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/LICENSE +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/README.md +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/setup.cfg +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/__main__.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/_js.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/account.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/asks.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/attachments.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/auto.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/auto_runner.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/cli.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/codekeys.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/codetools.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/compress.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/computers.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/confidential.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/confidential_models.json +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/connector.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/devicelink.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/dirs.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/folders.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/gateway.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/keys.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/link.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/mkdir.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/models.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/net.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/offered_models.json +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/opencode_plugins/notes-init.md +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/opencode_plugins/witbitz-media-server.mjs +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/opencode_plugins/witbitz-notes.js +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/opencode_plugins/witbitz-progress.js +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/outputs.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/pair.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/pairings.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/payers.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/plugins.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/policy.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/ports.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/qr.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/receipt.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/relay.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/seen.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/tinfoil_read.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/tools_catalog.json +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/tools_probe.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/toolsetup.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/ui.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/ui_static/app.css +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/ui_static/app.js +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/ui_static/index.html +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/uitools.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/winagent.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/winbg.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/winconsole.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/wizard.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/wslstart.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code.egg-info/SOURCES.txt +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code.egg-info/dependency_links.txt +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code.egg-info/entry_points.txt +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code.egg-info/requires.txt +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code.egg-info/top_level.txt +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_asks.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_attachments.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_auto.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_cli.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_codekeys.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_codetools.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_confidential.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_connector_e2e.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_devicelink.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_dirs.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_files_and_compress.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_folders.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_outputs.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_pair_flows.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_plugins.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_policy.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_ports.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_ports_win.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_registry.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_relay_codec.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_setup.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_tools_probe.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_toolsetup.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_ui.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_uitools.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_winagent.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_winbg.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_winconsole.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_windows_files.py +0 -0
- {witbitz_code-1.6.0 → witbitz_code-1.6.1}/tests/test_wslstart.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "witbitz-code"
|
|
7
|
-
version = "1.6.
|
|
7
|
+
version = "1.6.1"
|
|
8
8
|
description = "Reach OpenCode on this computer from the Witbitz Spaces Code section, through an end-to-end sealed relay."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -23,7 +23,7 @@ from dataclasses import dataclass, field
|
|
|
23
23
|
from pathlib import Path
|
|
24
24
|
from typing import Any
|
|
25
25
|
|
|
26
|
-
from . import keys, plugins
|
|
26
|
+
from . import keys, plugins, ports
|
|
27
27
|
from . import pairings as pp
|
|
28
28
|
from .wizard import find_opencode
|
|
29
29
|
|
|
@@ -138,6 +138,8 @@ def opencode_holders(data_dir: str) -> list[dict]:
|
|
|
138
138
|
cmd = ""
|
|
139
139
|
hits.append({"pid": int(p), "cmd": cmd})
|
|
140
140
|
return hits
|
|
141
|
+
if sys.platform == "win32": # no /proc, no lsof: every opencode.exe of this user's (the owner, 2026-10-09: the background
|
|
142
|
+
return win_opencode_processes() # copy's OpenCode held opencode.db and the delete died "WinError 32")
|
|
141
143
|
files = [os.path.join(data_dir, f) for f in ("opencode.db", "opencode.db-wal", "opencode.db-shm") if os.path.exists(os.path.join(data_dir, f))]
|
|
142
144
|
if not files or not shutil.which("lsof"):
|
|
143
145
|
return hits
|
|
@@ -150,6 +152,55 @@ def opencode_holders(data_dir: str) -> list[dict]:
|
|
|
150
152
|
return hits
|
|
151
153
|
|
|
152
154
|
|
|
155
|
+
def win_opencode_processes(*, run: Callable[[list[str]], str] | None = None, user: str | None = None) -> list[dict]:
|
|
156
|
+
"""Windows: this user's opencode.exe processes (tasklist, one CSV row each)."""
|
|
157
|
+
run = run or ports._run_text
|
|
158
|
+
user = os.environ.get("USERNAME", "") if user is None else user
|
|
159
|
+
hits = []
|
|
160
|
+
for line in run(["tasklist", "/V", "/FO", "CSV", "/NH", "/FI", "IMAGENAME eq opencode.exe"]).splitlines():
|
|
161
|
+
row = ports.parse_tasklist_row(line)
|
|
162
|
+
if row and (not user or row["user"].rsplit("\\", 1)[-1].lower() == user.lower()):
|
|
163
|
+
hits.append({"pid": row["pid"], "cmd": row["image"]})
|
|
164
|
+
return hits
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def running_witbitz(*, lock: Path | None = None, pairings: Callable[[], list] | None = None,
|
|
168
|
+
owners: Callable[[int], list] | None = None, alive: Callable[[int], bool] | None = None) -> list[dict]:
|
|
169
|
+
"""What runs witbitz-code here now: the page's manager (its ui.json names it — in the background it has no window to
|
|
170
|
+
close) and whatever holds each paired OpenCode port or its model proxy's (port + 100): a serve, its OpenCode."""
|
|
171
|
+
lock = lock or pp.pairings_path().parent / "ui.json"
|
|
172
|
+
pairings = pairings or (lambda: pp.load_pairings(log=lambda _m: None))
|
|
173
|
+
owners = owners or ports.port_owners
|
|
174
|
+
alive = alive or _alive
|
|
175
|
+
found: list[dict] = []
|
|
176
|
+
try:
|
|
177
|
+
pid = json.loads(lock.read_text(encoding="utf-8")).get("pid")
|
|
178
|
+
if isinstance(pid, int) and pid != os.getpid() and alive(pid):
|
|
179
|
+
found.append({"pid": pid, "cmd": "the Witbitz Code page"})
|
|
180
|
+
except (OSError, ValueError, AttributeError):
|
|
181
|
+
pass
|
|
182
|
+
for p in pairings():
|
|
183
|
+
tail = str(p.get("opencodeUrl") or "").rsplit(":", 1)[-1].rstrip("/")
|
|
184
|
+
port = int(tail) if tail.isdigit() else 0
|
|
185
|
+
for q in ([port, port + 100] if port else []):
|
|
186
|
+
for o in owners(q):
|
|
187
|
+
if o["pid"] != os.getpid() and all(o["pid"] != x["pid"] for x in found):
|
|
188
|
+
found.append({"pid": int(o["pid"]), "cmd": str(o.get("cmd") or "")[:70]})
|
|
189
|
+
return found
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _alive(pid: int) -> bool:
|
|
193
|
+
if sys.platform == "win32":
|
|
194
|
+
return _win_alive(pid)
|
|
195
|
+
try:
|
|
196
|
+
os.kill(pid, 0)
|
|
197
|
+
return True
|
|
198
|
+
except ProcessLookupError:
|
|
199
|
+
return False
|
|
200
|
+
except PermissionError:
|
|
201
|
+
return False # another user's: not ours
|
|
202
|
+
|
|
203
|
+
|
|
153
204
|
def _win_alive(pid: int) -> bool:
|
|
154
205
|
"""Windows: is `pid` still running? (OpenProcess + GetExitCodeProcess; access denied = another user's, still running.)"""
|
|
155
206
|
import ctypes # noqa: PLC0415 — Windows only
|
|
@@ -287,6 +338,7 @@ class Deps:
|
|
|
287
338
|
sessions: Callable[[], dict] = None # type: ignore[assignment]
|
|
288
339
|
delete_sessions: Callable[[], None] = None # type: ignore[assignment]
|
|
289
340
|
opencode_processes: Callable[[], list] = lambda: opencode_holders(str(keys.auth_path().parent))
|
|
341
|
+
running: Callable[[], list] = running_witbitz
|
|
290
342
|
stop_process: Callable[[int], bool] = stop_process
|
|
291
343
|
opencode: Callable[[], dict] = opencode_here
|
|
292
344
|
remove_opencode_program: Callable[[dict], dict] = remove_opencode_program
|
|
@@ -332,6 +384,12 @@ async def run_uninstall(d: Deps) -> dict:
|
|
|
332
384
|
how = {"installer": "from OpenCode's installer, in ~/.opencode", "npm": "with npm", "brew": "with Homebrew"}.get(oc["kind"])
|
|
333
385
|
remove_oc = ask(d.remove_opencode, f"Also remove OpenCode itself (installed {how})? [y/N] ") if oc["kind"] not in ("none", "other") else False
|
|
334
386
|
|
|
387
|
+
# The running witbitz-code first — the page's manager in the background, a serve, their OpenCode: it holds the files
|
|
388
|
+
# about to go (Windows refuses to delete an open file) and would keep answering the phone. Continue already said yes.
|
|
389
|
+
for p in d.running():
|
|
390
|
+
d.say(f"✓ Stopped the running witbitz-code: {p['cmd'] or 'a program'} (process {p['pid']})" if d.stop_process(p["pid"])
|
|
391
|
+
else f"✖ Could not stop {p['cmd'] or 'a program'} (process {p['pid']}) — close it, then run uninstall again")
|
|
392
|
+
|
|
335
393
|
# Sessions: an OpenCode that has its database open would write it back — never delete under it.
|
|
336
394
|
while remove_sessions:
|
|
337
395
|
procs = d.opencode_processes()
|
|
@@ -376,8 +434,11 @@ async def run_uninstall(d: Deps) -> dict:
|
|
|
376
434
|
d.remove_path(notes["root"])
|
|
377
435
|
d.say(f"✓ Deleted {notes['root']}")
|
|
378
436
|
if remove_sessions:
|
|
379
|
-
d.delete_sessions()
|
|
380
|
-
|
|
437
|
+
stuck = d.delete_sessions() or []
|
|
438
|
+
if stuck:
|
|
439
|
+
d.say(f"✖ Could not delete {', '.join(stuck[:4])} in {sessions['dir']} — another program still has it open; close OpenCode and delete it yourself")
|
|
440
|
+
else:
|
|
441
|
+
d.say(f"✓ Deleted the OpenCode sessions in {sessions['dir']} (provider logins kept)")
|
|
381
442
|
oc_gone = False
|
|
382
443
|
if remove_oc:
|
|
383
444
|
try:
|
|
@@ -454,12 +515,18 @@ def sessions_info() -> dict:
|
|
|
454
515
|
return {"dir": str(d), "exists": exists}
|
|
455
516
|
|
|
456
517
|
|
|
457
|
-
def delete_sessions() ->
|
|
518
|
+
def delete_sessions() -> list[str]:
|
|
519
|
+
"""→ the names that could not be deleted (Windows: a file another program still has open), never a crash."""
|
|
458
520
|
d = keys.auth_path().parent
|
|
521
|
+
left = []
|
|
459
522
|
for f in d.iterdir():
|
|
460
523
|
if f.name == "auth.json":
|
|
461
524
|
continue
|
|
462
|
-
|
|
525
|
+
try:
|
|
526
|
+
shutil.rmtree(f, ignore_errors=True) if f.is_dir() and not f.is_symlink() else f.unlink(missing_ok=True)
|
|
527
|
+
except OSError:
|
|
528
|
+
left.append(f.name)
|
|
529
|
+
return left
|
|
463
530
|
|
|
464
531
|
|
|
465
532
|
def saved_keys() -> list[str]:
|
|
@@ -72,7 +72,7 @@ class Fake:
|
|
|
72
72
|
remove_opencode_program=lambda info: self.done.append(("opencode",)) or {"ok": True, "said": []},
|
|
73
73
|
package=lambda: {"kind": self._pkg, "hint": "python3 -m pip uninstall witbitz-code"},
|
|
74
74
|
remove_package=lambda info: self.done.append(("package",)) or {"ok": True},
|
|
75
|
-
**{"login_start": lambda: None, "menu_remove": lambda: False, **over}) # never this machine's Windows Startup folder or Start menu
|
|
75
|
+
**{"login_start": lambda: None, "menu_remove": lambda: False, "running": lambda: [], **over}) # never this machine's Windows Startup folder or Start menu
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
PAIR = {"name": "desk", "account": "a@x.com", "idx": {"room": "r"}, "computerId": "c"}
|
|
@@ -174,3 +174,39 @@ def test_on_wsl_the_windows_startup_shortcut_setup_made_goes_too():
|
|
|
174
174
|
assert gone == ["Witbitz Code (WSL UbuntuD).lnk", "menu"]
|
|
175
175
|
assert any('Removed "Witbitz Code (WSL UbuntuD)" from the Start menu' in line for line in f.said)
|
|
176
176
|
assert any('Removed the Windows Startup shortcut "Witbitz Code (WSL UbuntuD)"' in line for line in f.said)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def test_the_running_witbitz_code_is_stopped_before_anything_is_deleted():
|
|
180
|
+
"""The owner, 2026-10-09 (Windows): the background copy's OpenCode held opencode.db and the delete died WinError 32."""
|
|
181
|
+
f = Fake(pairs=[PAIR], sessions=True, answers=["y", "y"])
|
|
182
|
+
run(un.run_uninstall(f.deps(running=lambda: [{"pid": 8420, "cmd": "the Witbitz Code page"}, {"pid": 19228, "cmd": "opencode.exe"}])))
|
|
183
|
+
stops = [i for i, x in enumerate(f.done) if x[0] == "stop"]
|
|
184
|
+
assert [f.done[i] for i in stops] == [("stop", 8420), ("stop", 19228)]
|
|
185
|
+
assert stops[-1] < f.done.index(("sessions",)) and stops[-1] < f.done.index(("rm", "/h/.witbitz/code"))
|
|
186
|
+
assert any("Stopped the running witbitz-code: the Witbitz Code page (process 8420)" in line for line in f.said)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def test_a_session_file_still_open_is_said_not_a_crash():
|
|
190
|
+
f = Fake(sessions=True, answers=["y", "y"])
|
|
191
|
+
d = f.deps()
|
|
192
|
+
d.delete_sessions = lambda: ["opencode.db"]
|
|
193
|
+
r = run(un.run_uninstall(d))
|
|
194
|
+
assert r.get("done") is not False
|
|
195
|
+
assert any("Could not delete opencode.db" in line for line in f.said)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def test_what_runs_witbitz_code_is_the_page_s_manager_and_the_paired_ports_owners(tmp_path):
|
|
199
|
+
lock = tmp_path / "ui.json"
|
|
200
|
+
lock.write_text('{"port": 4290, "token": "t", "pid": 8420}')
|
|
201
|
+
owners = {4097: [{"pid": 19228, "cmd": "opencode.exe"}], 4197: [{"pid": 8420, "cmd": "python.exe"}]}
|
|
202
|
+
got = un.running_witbitz(lock=lock, pairings=lambda: [{"opencodeUrl": "http://127.0.0.1:4097"}],
|
|
203
|
+
owners=lambda q: owners.get(q, []), alive=lambda pid: pid == 8420)
|
|
204
|
+
assert got == [{"pid": 8420, "cmd": "the Witbitz Code page"}, {"pid": 19228, "cmd": "opencode.exe"}]
|
|
205
|
+
lock.write_text('{"pid": 8420}')
|
|
206
|
+
assert un.running_witbitz(lock=lock, pairings=lambda: [], owners=lambda q: [], alive=lambda pid: False) == []
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def test_windows_finds_opencode_by_name():
|
|
210
|
+
out = '"opencode.exe","19228","Console","1","95,000 K","Running","ALONASUS\\shter","0:00:03","N/A"\n' \
|
|
211
|
+
'"opencode.exe","555","Console","1","1 K","Running","OTHER\\bob","0:00:01","N/A"\n'
|
|
212
|
+
assert un.win_opencode_processes(run=lambda argv: out, user="shter") == [{"pid": 19228, "cmd": "opencode.exe"}]
|
|
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
|
{witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/opencode_plugins/witbitz-media-server.mjs
RENAMED
|
File without changes
|
{witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/opencode_plugins/witbitz-notes.js
RENAMED
|
File without changes
|
{witbitz_code-1.6.0 → witbitz_code-1.6.1}/src/witbitz_code/opencode_plugins/witbitz-progress.js
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
|