mirror of
https://github.com/Such-Software/adaptive-multi-protocol-browser.git
synced 2026-10-21 16:28:32 +02:00
Add on-demand transport prompt output
This commit is contained in:
@@ -168,6 +168,9 @@ def _cmd_open(
|
||||
message=transport_result.message,
|
||||
transport_setup_status=transport_result.status,
|
||||
transport_setup_provider=transport_result.provider,
|
||||
transport_setup_owned=transport_result.owned,
|
||||
transport_setup_pid=transport_result.pid,
|
||||
transport_setup_endpoint=transport_result.endpoint,
|
||||
transport_setup_message=transport_result.message,
|
||||
)
|
||||
open_plan = execute_open(open_plan, root=Path.cwd())
|
||||
@@ -196,8 +199,15 @@ def _cmd_open(
|
||||
f"proxy={open_plan.proxy} "
|
||||
f"runtime_path={runtime_path} "
|
||||
f"user_js_path={user_js_path} "
|
||||
f"setup_prompt_title=\"{_safe(open_plan.setup_prompt_title)}\" "
|
||||
f"setup_prompt_body=\"{_safe(open_plan.setup_prompt_body)}\" "
|
||||
f"setup_prompt_approve_label=\"{_safe(open_plan.setup_prompt_approve_label)}\" "
|
||||
f"setup_prompt_approval_command=\"{_safe(open_plan.setup_prompt_approval_command)}\" "
|
||||
f"transport_setup_status={open_plan.transport_setup_status} "
|
||||
f"transport_setup_provider={open_plan.transport_setup_provider} "
|
||||
f"transport_setup_owned={str(open_plan.transport_setup_owned).lower()} "
|
||||
f"transport_setup_pid={open_plan.transport_setup_pid} "
|
||||
f"transport_setup_endpoint={open_plan.transport_setup_endpoint} "
|
||||
f"transport_setup_message=\"{_safe(open_plan.transport_setup_message)}\" "
|
||||
f"launch_command=\"{_safe(launch_command)}\" "
|
||||
f"setup_steps=\"{_safe(setup_steps)}\" "
|
||||
|
||||
@@ -5,6 +5,7 @@ from dataclasses import replace
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shlex
|
||||
import subprocess
|
||||
from urllib.parse import urlparse
|
||||
|
||||
@@ -34,8 +35,15 @@ class OpenPlan:
|
||||
message: str
|
||||
launch_spec: BrowserLaunchSpec | None = None
|
||||
browser_pid: int = 0
|
||||
setup_prompt_title: str = "-"
|
||||
setup_prompt_body: str = "-"
|
||||
setup_prompt_approve_label: str = "-"
|
||||
setup_prompt_approval_command: str = "-"
|
||||
transport_setup_status: str = "-"
|
||||
transport_setup_provider: str = "-"
|
||||
transport_setup_owned: bool = False
|
||||
transport_setup_pid: int = 0
|
||||
transport_setup_endpoint: str = "-"
|
||||
transport_setup_message: str = "-"
|
||||
|
||||
|
||||
@@ -68,6 +76,7 @@ def prepare_open(
|
||||
|
||||
if browse_plan.requires_consent:
|
||||
setup_steps = _setup_steps(browse_plan)
|
||||
setup_prompt = _setup_prompt(browse_plan, setup_steps)
|
||||
if not consent:
|
||||
return OpenPlan(
|
||||
browse_plan=browse_plan,
|
||||
@@ -79,6 +88,10 @@ def prepare_open(
|
||||
setup_steps=setup_steps,
|
||||
message=browse_plan.prompt,
|
||||
launch_spec=launch_spec,
|
||||
setup_prompt_title=setup_prompt.title,
|
||||
setup_prompt_body=setup_prompt.body,
|
||||
setup_prompt_approve_label=setup_prompt.approve_label,
|
||||
setup_prompt_approval_command=setup_prompt.approval_command,
|
||||
)
|
||||
return OpenPlan(
|
||||
browse_plan=browse_plan,
|
||||
@@ -90,6 +103,10 @@ def prepare_open(
|
||||
setup_steps=setup_steps,
|
||||
message="first-use setup approved; browser launch waits for transport readiness",
|
||||
launch_spec=launch_spec,
|
||||
setup_prompt_title=setup_prompt.title,
|
||||
setup_prompt_body=setup_prompt.body,
|
||||
setup_prompt_approve_label=setup_prompt.approve_label,
|
||||
setup_prompt_approval_command=setup_prompt.approval_command,
|
||||
)
|
||||
|
||||
return OpenPlan(
|
||||
@@ -166,6 +183,56 @@ def _setup_steps(browse_plan: BrowsePlan) -> tuple[str, ...]:
|
||||
return tuple(steps)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _SetupPrompt:
|
||||
title: str
|
||||
body: str
|
||||
approve_label: str
|
||||
approval_command: str
|
||||
|
||||
|
||||
def _setup_prompt(browse_plan: BrowsePlan, setup_steps: tuple[str, ...]) -> _SetupPrompt:
|
||||
transport = browse_plan.route.transport
|
||||
label = _transport_label(transport)
|
||||
platform = browse_plan.platform_capability.platform
|
||||
endpoint = browse_plan.status.endpoint if browse_plan.status else "-"
|
||||
setup_summary = "; ".join(setup_steps) if setup_steps else "prepare the transport"
|
||||
if browse_plan.status and not browse_plan.status.installed:
|
||||
availability = f"{label} is not installed or running."
|
||||
else:
|
||||
availability = f"{label} is not running."
|
||||
if platform == "desktop":
|
||||
management = f"AMPB can start a managed {label} session and keep its state isolated."
|
||||
elif platform == "android":
|
||||
management = f"AMPB can start a visible Android foreground {label} session."
|
||||
elif platform == "ios":
|
||||
management = f"AMPB can start a foreground-only in-app {label} session."
|
||||
else:
|
||||
management = f"AMPB can prepare {label} for this platform."
|
||||
body = (
|
||||
f"{availability} {management} The browser will use {endpoint} for "
|
||||
f"{browse_plan.route.normalized}. Setup plan: {setup_summary}."
|
||||
)
|
||||
approval_command = shlex.join(("ampbrowser", "open", browse_plan.route.normalized, "--yes", "--launch"))
|
||||
return _SetupPrompt(
|
||||
title=f"Set up {label}?",
|
||||
body=body,
|
||||
approve_label=f"Start {label} and open",
|
||||
approval_command=approval_command,
|
||||
)
|
||||
|
||||
|
||||
def _transport_label(transport: str) -> str:
|
||||
labels = {
|
||||
"tor": "Tor",
|
||||
"i2p": "I2P",
|
||||
"ipfs": "IPFS",
|
||||
"gemini": "Gemini",
|
||||
"reticulum": "Reticulum",
|
||||
}
|
||||
return labels.get(transport, transport)
|
||||
|
||||
|
||||
def _launch_spec_for(
|
||||
browse_plan: BrowsePlan,
|
||||
*,
|
||||
|
||||
@@ -158,17 +158,21 @@ def stop_managed_transport(
|
||||
)
|
||||
|
||||
if not _pid_alive(pid):
|
||||
_unlink_state(state_path)
|
||||
cleaned = _unlink_state(state_path)
|
||||
return ManagedTransportResult(
|
||||
transport,
|
||||
provider,
|
||||
"stale",
|
||||
"stale" if cleaned else "stale-cleanup-failed",
|
||||
endpoint,
|
||||
True,
|
||||
pid,
|
||||
state_dir,
|
||||
command,
|
||||
f"removed stale AMPB-owned {transport} state",
|
||||
(
|
||||
f"removed stale AMPB-owned {transport} state"
|
||||
if cleaned
|
||||
else f"could not remove stale AMPB-owned {transport} state"
|
||||
),
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -189,17 +193,21 @@ def stop_managed_transport(
|
||||
deadline = time.monotonic() + wait_seconds
|
||||
while time.monotonic() <= deadline:
|
||||
if not _pid_alive(pid):
|
||||
_unlink_state(state_path)
|
||||
cleaned = _unlink_state(state_path)
|
||||
return ManagedTransportResult(
|
||||
transport,
|
||||
provider,
|
||||
"stopped",
|
||||
"stopped" if cleaned else "stopped-cleanup-failed",
|
||||
endpoint,
|
||||
True,
|
||||
pid,
|
||||
state_dir,
|
||||
command,
|
||||
f"stopped AMPB-owned {transport}",
|
||||
(
|
||||
f"stopped AMPB-owned {transport}"
|
||||
if cleaned
|
||||
else f"stopped AMPB-owned {transport} but could not remove state"
|
||||
),
|
||||
)
|
||||
time.sleep(0.1)
|
||||
|
||||
@@ -404,17 +412,21 @@ def _owned_transport_result(
|
||||
command = tuple(str(part) for part in state.get("command", ()))
|
||||
|
||||
if not pid or not _pid_alive(pid):
|
||||
_unlink_state(state_path)
|
||||
cleaned = _unlink_state(state_path)
|
||||
return ManagedTransportResult(
|
||||
transport,
|
||||
provider,
|
||||
"stale",
|
||||
"stale" if cleaned else "stale-cleanup-failed",
|
||||
endpoint,
|
||||
True,
|
||||
pid,
|
||||
state_dir,
|
||||
command,
|
||||
f"removed stale AMPB-owned {transport} state",
|
||||
(
|
||||
f"removed stale AMPB-owned {transport} state"
|
||||
if cleaned
|
||||
else f"could not remove stale AMPB-owned {transport} state"
|
||||
),
|
||||
)
|
||||
|
||||
if _wait_for_endpoint(endpoint, timeout_seconds=wait_seconds):
|
||||
@@ -472,13 +484,14 @@ def _pid_alive(pid: int) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def _unlink_state(path: Path) -> None:
|
||||
def _unlink_state(path: Path) -> bool:
|
||||
try:
|
||||
path.unlink()
|
||||
return True
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return True
|
||||
except OSError:
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def _endpoint_for(transport: str) -> str:
|
||||
|
||||
Reference in New Issue
Block a user