Release Vulpes OS 2.7-preview.22

This commit is contained in:
OverSu 2026-10-22 20:42:26 +02:00
commit a138f97877
294 changed files with 515786 additions and 187 deletions

View file

@ -0,0 +1,81 @@
# SPDX-License-Identifier: MPL-2.0
"""Small client for the Gecko 48 debugger exposed by KaiOS over ADB."""
import json
import socket
import subprocess
class KaiOSDebugger:
def __init__(self, serial):
self.adb = ['adb', '-s', serial]
self.port = None
self.socket = None
def __enter__(self):
self.port = subprocess.check_output(self.adb + [
'forward', 'tcp:0', 'localfilesystem:/data/local/debugger-socket'],
text=True, timeout=15).strip()
try:
self.socket = socket.create_connection(('127.0.0.1', int(self.port)), timeout=20)
self.greeting = self.receive()
self.root = self.request('root', 'listTabs')
return self
except BaseException:
self.__exit__(None, None, None)
raise
def __exit__(self, *unused):
if self.socket:
self.socket.close()
if self.port:
subprocess.run(self.adb + ['forward', '--remove', 'tcp:' + self.port],
check=True, timeout=15)
def receive(self):
prefix = bytearray()
while True:
byte = self.socket.recv(1)
if not byte:
raise EOFError('KaiOS debugger disconnected')
if byte == b':':
break
prefix.extend(byte)
if len(prefix) > 12:
raise ValueError('Invalid debugger packet header')
remaining = int(prefix)
if remaining > 16 * 1024 * 1024:
raise ValueError('Debugger packet exceeds diagnostic limit')
data = bytearray()
while remaining:
part = self.socket.recv(remaining)
if not part:
raise EOFError('Incomplete debugger packet')
data.extend(part)
remaining -= len(part)
return json.loads(data)
def request(self, actor, kind, **fields):
body = json.dumps(dict(to=actor, type=kind, **fields)).encode()
self.socket.sendall(str(len(body)).encode() + b':' + body)
while True:
result = self.receive()
if result.get('from') != actor or result.get('type') in (
'consoleAPICall', 'pageError', 'networkEvent', 'newGlobal'):
continue
if 'error' in result:
raise RuntimeError(json.dumps(result))
return result
def evaluate(self, console, expression):
result = self.request(console, 'evaluateJS', text=expression)
if result.get('exceptionMessage'):
raise RuntimeError(str(result['exceptionMessage']))
value = result.get('result')
if isinstance(value, dict) and value.get('type') == 'longString':
actor = value['actor']
try:
value = self.request(actor, 'substring', start=0,
end=value['length'])['substring']
finally:
self.request(actor, 'release')
return value