summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>2026-02-04 13:50:44 +0000
committercopilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>2026-02-04 13:50:44 +0000
commitee0dfbeec44706c8b498f6582d1cfa8e5f765453 (patch)
tree23a44574f7282ebfd7175bc65e2015f30a62e4c2
parente63129be2aca1418d29d06e746dd00dffb8bd126 (diff)
downloaddecky-installer-ee0dfbeec44706c8b498f6582d1cfa8e5f765453.tar.gz
decky-installer-ee0dfbeec44706c8b498f6582d1cfa8e5f765453.zip
Add custom store configuration support to mock server and installer
Co-authored-by: tranch <5999732+tranch@users.noreply.github.com>
-rw-r--r--decky_plugin_installer.py88
-rw-r--r--mock_decky_server.py76
2 files changed, 161 insertions, 3 deletions
diff --git a/decky_plugin_installer.py b/decky_plugin_installer.py
index 7c70235..5814427 100644
--- a/decky_plugin_installer.py
+++ b/decky_plugin_installer.py
@@ -229,9 +229,91 @@ async def run_installer(target_id: int, store_url: str) -> None:
raise RuntimeError("Installation did not complete successfully")
+async def configure_store_url(store_url: str) -> None:
+ """Configure custom store URL in Decky settings."""
+ client = DeckyClient()
+ try:
+ log(f"Connecting to Decky server at {client.host}:{client.port}...")
+ token = await client.get_token()
+ await client.connect(token)
+
+ log(f"Setting custom store URL: {store_url}")
+ await client.send(CALL, "utilities/settings/set", ["store_url", store_url])
+
+ # Wait for reply
+ msg = await client.recv()
+ if msg is None:
+ raise RuntimeError("Connection closed by server")
+
+ m_type = msg.get("type")
+
+ if m_type == REPLY:
+ log(f"Store URL configured successfully: {msg.get('result')}")
+ elif m_type == ERROR:
+ log(f"Server error: {msg.get('error')}")
+ raise RuntimeError(f"Failed to set store URL: {msg.get('error')}")
+
+ except Exception as e:
+ log(f"Error: {e}")
+ raise
+ finally:
+ await client.close()
+
+
+async def get_store_url() -> str:
+ """Get the configured custom store URL from Decky settings."""
+ client = DeckyClient()
+ try:
+ log(f"Connecting to Decky server at {client.host}:{client.port}...")
+ token = await client.get_token()
+ await client.connect(token)
+
+ log("Getting configured store URL...")
+ await client.send(CALL, "utilities/settings/get", ["store_url", "https://plugins.deckbrew.xyz/plugins"])
+
+ # Wait for reply
+ msg = await client.recv()
+ if msg is None:
+ raise RuntimeError("Connection closed by server")
+
+ m_type = msg.get("type")
+
+ if m_type == REPLY:
+ store_url = msg.get('result')
+ log(f"Current store URL: {store_url}")
+ return store_url
+ elif m_type == ERROR:
+ log(f"Server error: {msg.get('error')}")
+ raise RuntimeError(f"Failed to get store URL: {msg.get('error')}")
+
+ raise RuntimeError("Unexpected response type")
+
+ except Exception as e:
+ log(f"Error: {e}")
+ raise
+ finally:
+ await client.close()
+
+
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Decky Plugin Installer")
- parser.add_argument("--store-url", default="http://127.0.0.1:1337/plugins")
- parser.add_argument("--target-id", type=int, default=42)
+ parser.add_argument("--store-url", default="http://127.0.0.1:1337/plugins",
+ help="Plugin store URL to fetch plugins from")
+ parser.add_argument("--target-id", type=int, default=42,
+ help="Plugin ID to install")
+ parser.add_argument("--configure-store", metavar="URL",
+ help="Configure custom store URL in Decky settings")
+ parser.add_argument("--get-store", action="store_true",
+ help="Get the configured custom store URL")
args = parser.parse_args()
- asyncio.run(run_installer(**vars(args)))
+
+ if args.configure_store:
+ # Configure store URL
+ asyncio.run(configure_store_url(args.configure_store))
+ elif args.get_store:
+ # Get configured store URL
+ asyncio.run(get_store_url())
+ else:
+ # Run installer
+ asyncio.run(run_installer(**{k: v for k, v in vars(args).items()
+ if k in ['target_id', 'store_url']}))
diff --git a/mock_decky_server.py b/mock_decky_server.py
index 7a7341e..7a74dcd 100644
--- a/mock_decky_server.py
+++ b/mock_decky_server.py
@@ -42,6 +42,9 @@ CSRF_TOKEN = "decky-" + os.urandom(16).hex()
# Plugin install requests storage (simulates PluginBrowser.install_requests)
install_requests: Dict[str, Dict[str, str]] = {}
+# Settings storage (simulates SettingsManager)
+settings_store: Dict[str, Any] = {}
+
logging.basicConfig(
level=logging.INFO,
@@ -198,6 +201,8 @@ def handle_call_route(
"utilities/install_plugin": handle_install_plugin,
"utilities/confirm_plugin_install": handle_confirm_plugin_install,
"utilities/cancel_plugin_install": handle_cancel_plugin_install,
+ "utilities/settings/get": handle_get_setting,
+ "utilities/settings/set": handle_set_setting,
}
if route not in routes:
@@ -409,6 +414,77 @@ def handle_cancel_plugin_install(
return None
+def handle_get_setting(
+ sock: socket.socket,
+ args: List[Any],
+ config: Dict[str, bool]
+) -> Any:
+ """Handle utilities/settings/get route.
+
+ Corresponds to:
+ - utilities.py async def get_setting() (line 272)
+ - settings.py def getSetting() (line 58)
+
+ Function signature from utilities.py:
+ async def get_setting(self, key: str, default: Any)
+
+ Args:
+ sock: The WebSocket socket (unused).
+ args: [key, default].
+ config: Server configuration (unused).
+
+ Returns:
+ The setting value or the default if not found.
+ """
+ if len(args) < 1:
+ raise ValueError("get_setting requires key argument")
+
+ key = args[0]
+ default = args[1] if len(args) > 1 else None
+
+ value = settings_store.get(key, default)
+ logger.info("[get_setting] key=%s, default=%s, value=%s", key, default, value)
+
+ return value
+
+
+def handle_set_setting(
+ sock: socket.socket,
+ args: List[Any],
+ config: Dict[str, bool]
+) -> Any:
+ """Handle utilities/settings/set route.
+
+ Corresponds to:
+ - utilities.py async def set_setting() (line 275)
+ - settings.py def setSetting() (line 61)
+
+ Function signature from utilities.py:
+ async def set_setting(self, key: str, value: Any)
+
+ Args:
+ sock: The WebSocket socket (unused).
+ args: [key, value].
+ config: Server configuration (unused).
+
+ Returns:
+ The value that was set.
+
+ Raises:
+ ValueError: If key or value is missing.
+ """
+ if len(args) < 2:
+ raise ValueError("set_setting requires key and value arguments")
+
+ key = args[0]
+ value = args[1]
+
+ settings_store[key] = value
+ logger.info("[set_setting] key=%s, value=%s", key, value)
+
+ return value
+
+
def _do_install(sock: socket.socket, artifact: str, name: str, version: str, hash_val: str) -> None:
"""Simulate the installation process with progress events.