browser-workspace 0.4.1 → 0.4.5
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.
- package/README.md +16 -2
- package/SKILL.md +60 -37
- package/bin/__pycache__/browser-workspacecpython-311.pyc +0 -0
- package/bin/browser-workspace +174 -13
- package/package.json +1 -1
- package/platform_runner.py +23 -6
- package/platforms/chatgpt/actions/_temporary_submit.py +22 -2
- package/platforms/chatgpt/tests/test_contract.py +7 -0
- package/platforms/wechat-channels/actions/_common.py +1 -1
- package/platforms/wechat-channels/actions/_post.py +37 -38
- package/platforms/wechat-channels/manifest.yaml +19 -13
- package/platforms/xhs/actions/_post.py +109 -20
- package/platforms/xhs/manifest.yaml +14 -5
- package/platforms/xhs/tests/test_contract.py +17 -0
- package/platforms/youtube/actions/_post.py +7 -4
- package/pyproject.toml +6 -2
- package/session_client.py +21 -11
- package/session_daemon.py +115 -9
- package/src/browser_workspace.egg-info/PKG-INFO +2 -1
- package/src/browser_workspace.egg-info/SOURCES.txt +84 -15
- package/src/browser_workspace.egg-info/entry_points.txt +2 -0
- package/src/browser_workspace.egg-info/requires.txt +1 -0
- package/src/browser_workspace.egg-info/top_level.txt +1 -1
- package/src/browser_workspace_app/__init__.py +1 -0
- package/src/browser_workspace_app/agent-workspace/agent_helpers.py +718 -0
- package/src/browser_workspace_app/cli.py +236 -0
- package/src/browser_workspace_app/extension/manifest.json +26 -0
- package/src/browser_workspace_app/extension/service-worker.mjs +126 -0
- package/src/browser_workspace_app/extension/workspace-manager.mjs +680 -0
- package/src/browser_workspace_app/extension/workspace-page.mjs +7 -0
- package/src/browser_workspace_app/extension/workspace.html +8 -0
- package/src/browser_workspace_app/interaction-skills/connection.md +52 -0
- package/src/browser_workspace_app/interaction-skills/cookies.md +3 -0
- package/src/browser_workspace_app/interaction-skills/cross-origin-iframes.md +3 -0
- package/src/browser_workspace_app/interaction-skills/dialogs.md +64 -0
- package/src/browser_workspace_app/interaction-skills/downloads.md +3 -0
- package/src/browser_workspace_app/interaction-skills/drag-and-drop.md +3 -0
- package/src/browser_workspace_app/interaction-skills/dropdowns.md +3 -0
- package/src/browser_workspace_app/interaction-skills/iframes.md +3 -0
- package/src/browser_workspace_app/interaction-skills/network-requests.md +3 -0
- package/src/browser_workspace_app/interaction-skills/print-as-pdf.md +3 -0
- package/src/browser_workspace_app/interaction-skills/profile-sync.md +90 -0
- package/src/browser_workspace_app/interaction-skills/screenshots.md +17 -0
- package/src/browser_workspace_app/interaction-skills/scrolling.md +22 -0
- package/src/browser_workspace_app/interaction-skills/shadow-dom.md +3 -0
- package/src/browser_workspace_app/interaction-skills/tabs.md +73 -0
- package/src/browser_workspace_app/interaction-skills/uploads.md +1 -0
- package/src/browser_workspace_app/interaction-skills/viewport.md +16 -0
- package/src/browser_workspace_app/licenses/browser-harness-MIT.txt +21 -0
- package/src/browser_workspace_app/managed_chrome.py +244 -0
- package/src/browser_workspace_app/node/admin.mjs +44 -0
- package/src/browser_workspace_app/package.json +36 -0
- package/src/browser_workspace_app/platform_runner.py +204 -0
- package/src/browser_workspace_app/platforms/chatgpt/README.md +60 -0
- package/src/browser_workspace_app/platforms/chatgpt/actions/_bootstrap_start.py +58 -0
- package/src/browser_workspace_app/platforms/chatgpt/actions/_lifecycle_common.py +119 -0
- package/src/browser_workspace_app/platforms/chatgpt/actions/_mcp_app.py +80 -0
- package/src/browser_workspace_app/platforms/chatgpt/actions/_new_thread.py +85 -0
- package/src/browser_workspace_app/platforms/chatgpt/actions/_new_turn.py +33 -0
- package/src/browser_workspace_app/platforms/chatgpt/actions/_project_setup.py +353 -0
- package/src/browser_workspace_app/platforms/chatgpt/actions/_readiness.py +52 -0
- package/src/browser_workspace_app/platforms/chatgpt/actions/_submit_thread.py +129 -0
- package/src/browser_workspace_app/platforms/chatgpt/actions/_temporary_submit.py +591 -0
- package/src/browser_workspace_app/platforms/chatgpt/actions/_thread_turn.py +362 -0
- package/src/browser_workspace_app/platforms/chatgpt/manifest.yaml +34 -0
- package/src/browser_workspace_app/platforms/chatgpt/tests/test_contract.py +183 -0
- package/src/browser_workspace_app/platforms/chrome-web-store/README.md +49 -0
- package/src/browser_workspace_app/platforms/chrome-web-store/actions/_chrome_web_store.py +425 -0
- package/src/browser_workspace_app/platforms/chrome-web-store/flows/check-status.md +7 -0
- package/src/browser_workspace_app/platforms/chrome-web-store/flows/open-item.md +10 -0
- package/src/browser_workspace_app/platforms/chrome-web-store/flows/submit-review.md +10 -0
- package/src/browser_workspace_app/platforms/chrome-web-store/flows/update-listing.md +18 -0
- package/src/browser_workspace_app/platforms/chrome-web-store/flows/upload-package.md +11 -0
- package/src/browser_workspace_app/platforms/chrome-web-store/flows/verify-published.md +9 -0
- package/src/browser_workspace_app/platforms/chrome-web-store/manifest.yaml +33 -0
- package/src/browser_workspace_app/platforms/chrome-web-store/tests/test_contract.py +83 -0
- package/src/browser_workspace_app/platforms/microsoft-teams/README.md +32 -0
- package/src/browser_workspace_app/platforms/microsoft-teams/actions/_meeting.py +210 -0
- package/src/browser_workspace_app/platforms/microsoft-teams/flows/instant-meeting.md +21 -0
- package/src/browser_workspace_app/platforms/microsoft-teams/manifest.yaml +25 -0
- package/src/browser_workspace_app/platforms/microsoft-teams/tests/test_contract.py +24 -0
- package/src/browser_workspace_app/platforms/tiktok/README.md +10 -0
- package/src/browser_workspace_app/platforms/tiktok/actions/_post.py +180 -0
- package/src/browser_workspace_app/platforms/tiktok/manifest.yaml +99 -0
- package/src/browser_workspace_app/platforms/wechat-channels/README.md +10 -0
- package/src/browser_workspace_app/platforms/wechat-channels/actions/_common.py +163 -0
- package/src/browser_workspace_app/platforms/wechat-channels/actions/_manage.py +130 -0
- package/src/browser_workspace_app/platforms/wechat-channels/actions/_post.py +231 -0
- package/src/browser_workspace_app/platforms/wechat-channels/manifest.yaml +124 -0
- package/src/browser_workspace_app/platforms/wechat-channels/tests/test_contract.py +36 -0
- package/src/browser_workspace_app/platforms/xhs/README.md +10 -0
- package/src/browser_workspace_app/platforms/xhs/actions/_manage.py +355 -0
- package/src/browser_workspace_app/platforms/xhs/actions/_post.py +281 -0
- package/src/browser_workspace_app/platforms/xhs/manifest.yaml +107 -0
- package/src/browser_workspace_app/platforms/xhs/tests/test_contract.py +34 -0
- package/src/browser_workspace_app/platforms/youtube/README.md +10 -0
- package/src/browser_workspace_app/platforms/youtube/actions/_post.py +103 -0
- package/src/browser_workspace_app/platforms/youtube/manifest.yaml +94 -0
- package/src/browser_workspace_app/pyproject.toml +33 -0
- package/src/browser_workspace_app/session_client.py +107 -0
- package/src/browser_workspace_app/session_daemon.py +431 -0
- package/src/browser_harness/__init__.py +0 -2
- package/src/browser_harness/__pycache__/__init__.cpython-311.pyc +0 -0
- package/src/browser_harness/_ipc.py +0 -201
- package/src/browser_harness/admin.py +0 -1588
- package/src/browser_harness/auth.py +0 -546
- package/src/browser_harness/daemon.py +0 -894
- package/src/browser_harness/helpers.py +0 -668
- package/src/browser_harness/macos.py +0 -131
- package/src/browser_harness/mcp_cli.py +0 -16
- package/src/browser_harness/paths.py +0 -49
- package/src/browser_harness/recorder.py +0 -343
- package/src/browser_harness/run.py +0 -413
- package/src/browser_harness/telemetry.py +0 -308
- package/src/browser_harness/video-template.html +0 -970
- package/src/browser_harness/video.py +0 -749
- package/src/browser_harness/video_render.py +0 -524
package/session_daemon.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
import ast, atexit, contextlib, io, json, os, secrets, socket, sys, threading, time, traceback
|
|
2
|
+
import ast, atexit, contextlib, io, json, os, secrets, signal, socket, sys, threading, time, traceback
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
5
|
ROOT = Path(__file__).resolve().parent
|
|
@@ -14,18 +14,80 @@ os.environ.setdefault('BH_WORKSPACE_NAME', 'Harness')
|
|
|
14
14
|
|
|
15
15
|
from managed_chrome import ensure_managed_chrome
|
|
16
16
|
MANAGED_CHROME = ensure_managed_chrome()
|
|
17
|
-
from browser_harness.admin import ensure_daemon
|
|
18
|
-
|
|
17
|
+
from browser_harness.admin import ensure_daemon, _process_start_time
|
|
18
|
+
from browser_harness import _ipc as harness_ipc
|
|
19
19
|
from browser_harness import helpers as bh
|
|
20
20
|
|
|
21
|
+
HARNESS_OWNER_TOKEN = secrets.token_hex(24)
|
|
22
|
+
HARNESS_OWNER_PID = os.getpid()
|
|
23
|
+
HARNESS_OWNER_STARTED = _process_start_time(HARNESS_OWNER_PID)
|
|
24
|
+
HARNESS_OWNER_PIPE = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def stop_owned_harness():
|
|
28
|
+
"""Only a harness matching this daemon generation may stop."""
|
|
29
|
+
try:
|
|
30
|
+
conn, token = harness_ipc.connect(os.environ.get('BU_NAME', 'browser-workspace'), timeout=1)
|
|
31
|
+
with conn:
|
|
32
|
+
response = harness_ipc.request(conn, token, {'meta': 'owner_shutdown', 'owner_token': HARNESS_OWNER_TOKEN})
|
|
33
|
+
if isinstance(response, dict) and response.get('ok'):
|
|
34
|
+
# Allow the harness its graceful CDP/IPC cleanup before EOF of
|
|
35
|
+
# our owner pipe forces the crash-only exit path.
|
|
36
|
+
deadline = time.monotonic() + 2
|
|
37
|
+
while time.monotonic() < deadline and harness_ipc.ping(os.environ.get('BU_NAME', 'browser-workspace'), timeout=0.1):
|
|
38
|
+
time.sleep(0.05)
|
|
39
|
+
except (OSError, ValueError, TimeoutError):
|
|
40
|
+
pass
|
|
41
|
+
|
|
21
42
|
DEFAULT_WORKSPACE = os.environ.get('BH_WORKSPACE_NAME','Harness')
|
|
22
43
|
RUNTIME_DIR = Path.home()/'.config/browser-workspace/runtime'
|
|
23
44
|
SOCKET_PATH = (Path(os.environ['BROWSER_WORKSPACE_SESSION_SOCKET']) if os.environ.get('BROWSER_WORKSPACE_TEST_MODE')=='1' and os.environ.get('BROWSER_WORKSPACE_SESSION_SOCKET') else RUNTIME_DIR/'session.sock')
|
|
24
|
-
OWNER_LOCK_PATH = RUNTIME_DIR/'session
|
|
45
|
+
OWNER_LOCK_PATH = RUNTIME_DIR/'session.lock'
|
|
25
46
|
SESSIONS = {}
|
|
26
47
|
SESSIONS_LOCK = threading.Lock()
|
|
27
48
|
BROWSER_LOCK = threading.RLock()
|
|
28
49
|
|
|
50
|
+
SESSION_RECONCILE_SECONDS = 30
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def is_reclaimed(info):
|
|
54
|
+
url = info.get('url', '')
|
|
55
|
+
if not url.startswith('chrome-extension://'):
|
|
56
|
+
return False
|
|
57
|
+
try:
|
|
58
|
+
from urllib.parse import urlparse, parse_qs
|
|
59
|
+
parsed = urlparse(url)
|
|
60
|
+
return parsed.path == '/workspace.html' and parse_qs(parsed.query).get('role') == ['idle']
|
|
61
|
+
except ValueError:
|
|
62
|
+
return False
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def reconcile_sessions():
|
|
66
|
+
"""Drop records for completely released leases, never release those tabs again."""
|
|
67
|
+
with BROWSER_LOCK:
|
|
68
|
+
try:
|
|
69
|
+
targets = bh.cdp('Target.getTargets')['targetInfos']
|
|
70
|
+
except Exception:
|
|
71
|
+
return []
|
|
72
|
+
pages = {i['targetId']: i for i in targets if i.get('type') == 'page'}
|
|
73
|
+
removed = []
|
|
74
|
+
with SESSIONS_LOCK:
|
|
75
|
+
for sid, session in list(SESSIONS.items()):
|
|
76
|
+
if session.lock.locked():
|
|
77
|
+
continue
|
|
78
|
+
# A leased root may have opened child tabs: keep any live child.
|
|
79
|
+
if all(tid not in pages or is_reclaimed(pages[tid])
|
|
80
|
+
for tid in session.owned_target_ids):
|
|
81
|
+
del SESSIONS[sid]
|
|
82
|
+
removed.append(sid)
|
|
83
|
+
return removed
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def reconciliation_loop():
|
|
87
|
+
while True:
|
|
88
|
+
time.sleep(SESSION_RECONCILE_SECONDS)
|
|
89
|
+
reconcile_sessions()
|
|
90
|
+
|
|
29
91
|
|
|
30
92
|
def compilable_module_body(body):
|
|
31
93
|
"""Return a module body that remains valid after trailing-result extraction.
|
|
@@ -84,10 +146,13 @@ class Session:
|
|
|
84
146
|
return result
|
|
85
147
|
|
|
86
148
|
def _cdp(self, method, **kwargs):
|
|
149
|
+
if method == 'Target.createTarget':
|
|
150
|
+
raise RuntimeError(
|
|
151
|
+
'Target.createTarget is disabled in Browser Workspace sessions; '
|
|
152
|
+
'use new_tab(url) so the tab is owned by the active session/workspace'
|
|
153
|
+
)
|
|
87
154
|
result=bh.cdp(method, **kwargs)
|
|
88
|
-
if method == 'Target.
|
|
89
|
-
self._remember_target(result.get('targetId'))
|
|
90
|
-
elif method == 'Target.closeTarget':
|
|
155
|
+
if method == 'Target.closeTarget':
|
|
91
156
|
self.owned_target_ids.discard(kwargs.get('targetId'))
|
|
92
157
|
return result
|
|
93
158
|
|
|
@@ -253,12 +318,31 @@ def stop_session(sid):
|
|
|
253
318
|
if errors: release_error='; '.join(errors)
|
|
254
319
|
return {'session_id':sid,'workspace':s.workspace,'target_id':s.target_id,'closed_tabs':closed_count,'release_error':release_error}
|
|
255
320
|
|
|
321
|
+
SOCKET_IDENTITY = None
|
|
322
|
+
|
|
323
|
+
def remove_owned_socket():
|
|
324
|
+
"""Never unlink a socket replaced by another owner."""
|
|
325
|
+
if SOCKET_IDENTITY is None:
|
|
326
|
+
return
|
|
327
|
+
try:
|
|
328
|
+
st = SOCKET_PATH.lstat()
|
|
329
|
+
if (st.st_dev, st.st_ino) == SOCKET_IDENTITY:
|
|
330
|
+
SOCKET_PATH.unlink()
|
|
331
|
+
except FileNotFoundError:
|
|
332
|
+
pass
|
|
333
|
+
|
|
256
334
|
def cleanup():
|
|
257
335
|
with SESSIONS_LOCK: ids=list(SESSIONS)
|
|
258
336
|
for sid in ids:
|
|
259
337
|
try: stop_session(sid)
|
|
260
338
|
except Exception: pass
|
|
261
|
-
|
|
339
|
+
stop_owned_harness()
|
|
340
|
+
# The write end is close-on-exec; its final close also detects SIGKILL
|
|
341
|
+
# and parent re-exec without relying on a recycled numeric PID.
|
|
342
|
+
if HARNESS_OWNER_PIPE is not None:
|
|
343
|
+
try: os.close(HARNESS_OWNER_PIPE)
|
|
344
|
+
except OSError: pass
|
|
345
|
+
try: remove_owned_socket()
|
|
262
346
|
except Exception: pass
|
|
263
347
|
atexit.register(cleanup)
|
|
264
348
|
|
|
@@ -306,6 +390,7 @@ def serve_conn(conn):
|
|
|
306
390
|
f.write((json.dumps(result,ensure_ascii=False)+'\n').encode()); f.flush()
|
|
307
391
|
|
|
308
392
|
def main():
|
|
393
|
+
global SOCKET_IDENTITY
|
|
309
394
|
RUNTIME_DIR.mkdir(parents=True,exist_ok=True)
|
|
310
395
|
try: os.chmod(RUNTIME_DIR,0o700)
|
|
311
396
|
except Exception: pass
|
|
@@ -315,8 +400,29 @@ def main():
|
|
|
315
400
|
fcntl.flock(owner,fcntl.LOCK_EX|fcntl.LOCK_NB)
|
|
316
401
|
except BlockingIOError:
|
|
317
402
|
owner.close(); return
|
|
403
|
+
global HARNESS_OWNER_PIPE
|
|
404
|
+
read_fd, write_fd = os.pipe() if os.name == 'posix' else (None, None)
|
|
405
|
+
HARNESS_OWNER_PIPE = write_fd
|
|
406
|
+
try:
|
|
407
|
+
owner_env = {
|
|
408
|
+
'BH_OWNER_PID': str(HARNESS_OWNER_PID),
|
|
409
|
+
'BH_OWNER_STARTED': str(HARNESS_OWNER_STARTED or ''),
|
|
410
|
+
'BH_OWNER_TOKEN': HARNESS_OWNER_TOKEN,
|
|
411
|
+
}
|
|
412
|
+
if read_fd is not None:
|
|
413
|
+
owner_env['BH_OWNER_PIPE_FD'] = str(read_fd)
|
|
414
|
+
ensure_daemon(env=owner_env)
|
|
415
|
+
finally:
|
|
416
|
+
if read_fd is not None:
|
|
417
|
+
os.close(read_fd)
|
|
418
|
+
def terminate(_signum, _frame):
|
|
419
|
+
raise SystemExit(0)
|
|
420
|
+
signal.signal(signal.SIGTERM, terminate)
|
|
421
|
+
signal.signal(signal.SIGINT, terminate)
|
|
422
|
+
# Lock ownership is required before changing the shared socket path.
|
|
318
423
|
SOCKET_PATH.unlink(missing_ok=True)
|
|
319
|
-
srv=socket.socket(socket.AF_UNIX,socket.SOCK_STREAM); srv.bind(str(SOCKET_PATH)); os.chmod(SOCKET_PATH,0o600); srv.listen(32)
|
|
424
|
+
srv=socket.socket(socket.AF_UNIX,socket.SOCK_STREAM); srv.bind(str(SOCKET_PATH)); os.chmod(SOCKET_PATH,0o600); SOCKET_IDENTITY=(SOCKET_PATH.stat().st_dev, SOCKET_PATH.stat().st_ino); srv.listen(32)
|
|
425
|
+
threading.Thread(target=reconciliation_loop, daemon=True).start()
|
|
320
426
|
try:
|
|
321
427
|
while True:
|
|
322
428
|
conn,_=srv.accept(); threading.Thread(target=serve_conn,args=(conn,),daemon=True).start()
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: browser-workspace
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.5
|
|
4
4
|
Summary: Agent browser workspace with persistent Python sessions, tab leasing, snapshots, and platform workflows.
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
|
+
Requires-Dist: browser-harness @ git+https://github.com/lalalic/browser-harness.git@80b74e116b9126f5159c84e5e05a750573e5f192
|
|
6
7
|
Requires-Dist: cdp-use==1.4.5
|
|
7
8
|
Requires-Dist: fetch-use==0.4.0
|
|
8
9
|
Requires-Dist: pillow==12.3.0
|
|
@@ -1,28 +1,97 @@
|
|
|
1
1
|
README.md
|
|
2
2
|
pyproject.toml
|
|
3
|
-
src/browser_harness/__init__.py
|
|
4
|
-
src/browser_harness/_ipc.py
|
|
5
|
-
src/browser_harness/admin.py
|
|
6
|
-
src/browser_harness/auth.py
|
|
7
|
-
src/browser_harness/daemon.py
|
|
8
|
-
src/browser_harness/helpers.py
|
|
9
|
-
src/browser_harness/macos.py
|
|
10
|
-
src/browser_harness/mcp_cli.py
|
|
11
|
-
src/browser_harness/paths.py
|
|
12
|
-
src/browser_harness/recorder.py
|
|
13
|
-
src/browser_harness/run.py
|
|
14
|
-
src/browser_harness/telemetry.py
|
|
15
|
-
src/browser_harness/video-template.html
|
|
16
|
-
src/browser_harness/video.py
|
|
17
|
-
src/browser_harness/video_render.py
|
|
18
3
|
src/browser_workspace.egg-info/PKG-INFO
|
|
19
4
|
src/browser_workspace.egg-info/SOURCES.txt
|
|
20
5
|
src/browser_workspace.egg-info/dependency_links.txt
|
|
6
|
+
src/browser_workspace.egg-info/entry_points.txt
|
|
21
7
|
src/browser_workspace.egg-info/requires.txt
|
|
22
8
|
src/browser_workspace.egg-info/top_level.txt
|
|
9
|
+
src/browser_workspace_app/__init__.py
|
|
10
|
+
src/browser_workspace_app/cli.py
|
|
11
|
+
src/browser_workspace_app/managed_chrome.py
|
|
12
|
+
src/browser_workspace_app/package.json
|
|
13
|
+
src/browser_workspace_app/platform_runner.py
|
|
14
|
+
src/browser_workspace_app/pyproject.toml
|
|
15
|
+
src/browser_workspace_app/session_client.py
|
|
16
|
+
src/browser_workspace_app/session_daemon.py
|
|
17
|
+
src/browser_workspace_app/agent-workspace/agent_helpers.py
|
|
18
|
+
src/browser_workspace_app/extension/manifest.json
|
|
19
|
+
src/browser_workspace_app/extension/service-worker.mjs
|
|
20
|
+
src/browser_workspace_app/extension/workspace-manager.mjs
|
|
21
|
+
src/browser_workspace_app/extension/workspace-page.mjs
|
|
22
|
+
src/browser_workspace_app/extension/workspace.html
|
|
23
|
+
src/browser_workspace_app/interaction-skills/connection.md
|
|
24
|
+
src/browser_workspace_app/interaction-skills/cookies.md
|
|
25
|
+
src/browser_workspace_app/interaction-skills/cross-origin-iframes.md
|
|
26
|
+
src/browser_workspace_app/interaction-skills/dialogs.md
|
|
27
|
+
src/browser_workspace_app/interaction-skills/downloads.md
|
|
28
|
+
src/browser_workspace_app/interaction-skills/drag-and-drop.md
|
|
29
|
+
src/browser_workspace_app/interaction-skills/dropdowns.md
|
|
30
|
+
src/browser_workspace_app/interaction-skills/iframes.md
|
|
31
|
+
src/browser_workspace_app/interaction-skills/network-requests.md
|
|
32
|
+
src/browser_workspace_app/interaction-skills/print-as-pdf.md
|
|
33
|
+
src/browser_workspace_app/interaction-skills/profile-sync.md
|
|
34
|
+
src/browser_workspace_app/interaction-skills/screenshots.md
|
|
35
|
+
src/browser_workspace_app/interaction-skills/scrolling.md
|
|
36
|
+
src/browser_workspace_app/interaction-skills/shadow-dom.md
|
|
37
|
+
src/browser_workspace_app/interaction-skills/tabs.md
|
|
38
|
+
src/browser_workspace_app/interaction-skills/uploads.md
|
|
39
|
+
src/browser_workspace_app/interaction-skills/viewport.md
|
|
40
|
+
src/browser_workspace_app/licenses/browser-harness-MIT.txt
|
|
41
|
+
src/browser_workspace_app/node/admin.mjs
|
|
42
|
+
src/browser_workspace_app/platforms/chatgpt/README.md
|
|
43
|
+
src/browser_workspace_app/platforms/chatgpt/manifest.yaml
|
|
44
|
+
src/browser_workspace_app/platforms/chatgpt/actions/_bootstrap_start.py
|
|
45
|
+
src/browser_workspace_app/platforms/chatgpt/actions/_lifecycle_common.py
|
|
46
|
+
src/browser_workspace_app/platforms/chatgpt/actions/_mcp_app.py
|
|
47
|
+
src/browser_workspace_app/platforms/chatgpt/actions/_new_thread.py
|
|
48
|
+
src/browser_workspace_app/platforms/chatgpt/actions/_new_turn.py
|
|
49
|
+
src/browser_workspace_app/platforms/chatgpt/actions/_project_setup.py
|
|
50
|
+
src/browser_workspace_app/platforms/chatgpt/actions/_readiness.py
|
|
51
|
+
src/browser_workspace_app/platforms/chatgpt/actions/_submit_thread.py
|
|
52
|
+
src/browser_workspace_app/platforms/chatgpt/actions/_temporary_submit.py
|
|
53
|
+
src/browser_workspace_app/platforms/chatgpt/actions/_thread_turn.py
|
|
54
|
+
src/browser_workspace_app/platforms/chatgpt/tests/test_contract.py
|
|
55
|
+
src/browser_workspace_app/platforms/chrome-web-store/README.md
|
|
56
|
+
src/browser_workspace_app/platforms/chrome-web-store/manifest.yaml
|
|
57
|
+
src/browser_workspace_app/platforms/chrome-web-store/actions/_chrome_web_store.py
|
|
58
|
+
src/browser_workspace_app/platforms/chrome-web-store/flows/check-status.md
|
|
59
|
+
src/browser_workspace_app/platforms/chrome-web-store/flows/open-item.md
|
|
60
|
+
src/browser_workspace_app/platforms/chrome-web-store/flows/submit-review.md
|
|
61
|
+
src/browser_workspace_app/platforms/chrome-web-store/flows/update-listing.md
|
|
62
|
+
src/browser_workspace_app/platforms/chrome-web-store/flows/upload-package.md
|
|
63
|
+
src/browser_workspace_app/platforms/chrome-web-store/flows/verify-published.md
|
|
64
|
+
src/browser_workspace_app/platforms/chrome-web-store/tests/test_contract.py
|
|
65
|
+
src/browser_workspace_app/platforms/microsoft-teams/README.md
|
|
66
|
+
src/browser_workspace_app/platforms/microsoft-teams/manifest.yaml
|
|
67
|
+
src/browser_workspace_app/platforms/microsoft-teams/actions/_meeting.py
|
|
68
|
+
src/browser_workspace_app/platforms/microsoft-teams/flows/instant-meeting.md
|
|
69
|
+
src/browser_workspace_app/platforms/microsoft-teams/tests/test_contract.py
|
|
70
|
+
src/browser_workspace_app/platforms/tiktok/README.md
|
|
71
|
+
src/browser_workspace_app/platforms/tiktok/manifest.yaml
|
|
72
|
+
src/browser_workspace_app/platforms/tiktok/actions/_post.py
|
|
73
|
+
src/browser_workspace_app/platforms/wechat-channels/README.md
|
|
74
|
+
src/browser_workspace_app/platforms/wechat-channels/manifest.yaml
|
|
75
|
+
src/browser_workspace_app/platforms/wechat-channels/actions/_common.py
|
|
76
|
+
src/browser_workspace_app/platforms/wechat-channels/actions/_manage.py
|
|
77
|
+
src/browser_workspace_app/platforms/wechat-channels/actions/_post.py
|
|
78
|
+
src/browser_workspace_app/platforms/wechat-channels/tests/test_contract.py
|
|
79
|
+
src/browser_workspace_app/platforms/xhs/README.md
|
|
80
|
+
src/browser_workspace_app/platforms/xhs/manifest.yaml
|
|
81
|
+
src/browser_workspace_app/platforms/xhs/actions/_manage.py
|
|
82
|
+
src/browser_workspace_app/platforms/xhs/actions/_post.py
|
|
83
|
+
src/browser_workspace_app/platforms/xhs/tests/test_contract.py
|
|
84
|
+
src/browser_workspace_app/platforms/youtube/README.md
|
|
85
|
+
src/browser_workspace_app/platforms/youtube/manifest.yaml
|
|
86
|
+
src/browser_workspace_app/platforms/youtube/actions/_post.py
|
|
87
|
+
test/test_auth_cookie_audit.py
|
|
88
|
+
test/test_auth_keepalive_visit.py
|
|
89
|
+
test/test_harness_ownership.py
|
|
23
90
|
test/test_managed_chrome.py
|
|
24
91
|
test/test_platform_profile.py
|
|
25
92
|
test/test_platform_runner.py
|
|
93
|
+
test/test_pypi_package.py
|
|
26
94
|
test/test_session_cli.py
|
|
27
95
|
test/test_session_execution.py
|
|
96
|
+
test/test_session_reconcile.py
|
|
28
97
|
test/test_workspace_cli.py
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
browser_workspace_app
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Browser Workspace Python distribution."""
|