mirror of
https://github.com/yuga-hashimoto/openclaw-assistant.git
synced 2026-08-14 08:47:12 +00:00
fix: auto approve OpenClaw pairing via host command
This commit is contained in:
@@ -48,17 +48,6 @@ fun PairingRequiredCard(deviceId: String, displayName: String = "") {
|
||||
|
||||
suspend fun approveWithBestRoute(isAuto: Boolean) {
|
||||
runningCommand = true
|
||||
commandStatus = context.getString(
|
||||
if (isAuto) R.string.pairing_gateway_auto_running else R.string.pairing_gateway_running,
|
||||
)
|
||||
|
||||
val gatewayResult = nodeRuntime.approvePendingPairingForDevice(deviceId)
|
||||
if (gatewayResult.approved) {
|
||||
runningCommand = false
|
||||
commandStatus = context.getString(R.string.pairing_gateway_approve_sent)
|
||||
nodeRuntime.refreshGatewayConnection()
|
||||
return
|
||||
}
|
||||
|
||||
if (TerminalCommandClient.isConfigured(context) || HermesTerminalClient.resolveEndpoint(context) != null) {
|
||||
commandStatus = context.getString(
|
||||
@@ -88,8 +77,7 @@ fun PairingRequiredCard(deviceId: String, displayName: String = "") {
|
||||
}
|
||||
|
||||
runningCommand = false
|
||||
commandStatus = gatewayResult.message?.takeIf { it.isNotBlank() }
|
||||
?: context.getString(R.string.pairing_gateway_failed)
|
||||
commandStatus = context.getString(R.string.pairing_host_command_required, approveCommand)
|
||||
if (!isAuto) {
|
||||
val clip = ClipData.newPlainText("OpenClaw Approve", approveCommand)
|
||||
clipboardManager.setPrimaryClip(clip)
|
||||
@@ -155,6 +143,19 @@ fun PairingRequiredCard(deviceId: String, displayName: String = "") {
|
||||
style = MaterialTheme.typography.bodySmall
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
SelectionContainer {
|
||||
Text(
|
||||
text = approveCommand,
|
||||
style = MaterialTheme.typography.bodySmall.copy(fontFamily = FontFamily.Monospace),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(MaterialTheme.colorScheme.error.copy(alpha = 0.1f), RoundedCornerShape(4.dp))
|
||||
.padding(horizontal = 8.dp, vertical = 6.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
// Actions
|
||||
|
||||
@@ -326,13 +326,14 @@ Weitere Informationen finden Sie auf der offiziellen Website von VOICEVOX.</stri
|
||||
<string name="fix_request_message">Bitte gewähren Sie meinem aktuellen API-Token den Geltungsbereich „operator.read“.</string>
|
||||
<string name="action_ask_ai">Bitten Sie die KI, das Problem zu beheben</string>
|
||||
<string name="pairing_required_title">Gerätekopplung erforderlich</string>
|
||||
<string name="pairing_required_desc">Dieses Gerät ist noch nicht vom Server genehmigt. WakeHermesClaw versucht zuerst, es über OpenClaw zu genehmigen. Wenn das nicht verfügbar ist, führe den Befehl auf dem Host aus.</string>
|
||||
<string name="pairing_required_desc">Dieses Gerät ist noch nicht vom Server genehmigt. WakeHermesClaw versucht, es über den Host-Befehlsendpunkt des Setup-Links automatisch zu genehmigen. Wenn das nicht verfügbar ist, führe den Befehl auf dem Host aus.</string>
|
||||
<string name="pairing_requested_scopes">Angeforderte OpenClaw-Berechtigungen: operator.read, operator.write, operator.admin, operator.pairing, operator.talk.secrets, operator.approvals.</string>
|
||||
<string name="pairing_copy_command">Befehl kopieren</string>
|
||||
<string name="pairing_command_copied">Befehl in die Zwischenablage kopiert</string>
|
||||
<string name="pairing_device_id">Geräte-ID: %s</string>
|
||||
<string name="pairing_approve_command">Befehl genehmigen (Kopieren)</string>
|
||||
<string name="pairing_reject_command">Befehl ablehnen (Kopieren)</string>
|
||||
<string name="pairing_host_command_required">Auf dem OpenClaw-Host ausführen: %1$s</string>
|
||||
<string name="pairing_refresh_status">Status aktualisieren</string>
|
||||
<string name="pairing_guide_title">So genehmigen Sie dieses Gerät:</string>
|
||||
<string name="pairing_guide_step_1">1. Greifen Sie auf Ihr OpenClaw-Serverterminal zu.</string>
|
||||
|
||||
@@ -327,13 +327,14 @@ Para más detalles, consulta el sitio oficial de VOICEVOX.</string>
|
||||
<string name="fix_request_message">Por favor, otorgue alcance \'operator.read\' a mi token API actual.</string>
|
||||
<string name="action_ask_ai">Pídale a AI que lo arregle</string>
|
||||
<string name="pairing_required_title">Se requiere emparejamiento de dispositivos</string>
|
||||
<string name="pairing_required_desc">Este dispositivo aún no ha sido aprobado por el servidor. WakeHermesClaw intentará aprobarlo primero mediante OpenClaw; si no está disponible, ejecuta el comando en el host.</string>
|
||||
<string name="pairing_required_desc">Este dispositivo aún no ha sido aprobado por el servidor. WakeHermesClaw intentará aprobarlo automáticamente mediante el endpoint de comandos del host del enlace de configuración; si no está disponible, ejecuta el comando en el host.</string>
|
||||
<string name="pairing_requested_scopes">Permisos de OpenClaw solicitados: operator.read, operator.write, operator.admin, operator.pairing, operator.talk.secrets, operator.approvals.</string>
|
||||
<string name="pairing_copy_command">Copiar comando</string>
|
||||
<string name="pairing_command_copied">Comando copiado al portapapeles</string>
|
||||
<string name="pairing_device_id">ID del dispositivo: %s</string>
|
||||
<string name="pairing_approve_command">Aprobar comando (copia)</string>
|
||||
<string name="pairing_reject_command">Rechazar comando (Copiar)</string>
|
||||
<string name="pairing_host_command_required">Ejecuta esto en el host de OpenClaw: %1$s</string>
|
||||
<string name="pairing_refresh_status">Actualizar estado</string>
|
||||
<string name="pairing_guide_title">Cómo aprobar este dispositivo:</string>
|
||||
<string name="pairing_guide_step_1">1. Acceda a su terminal de servidor OpenClaw.</string>
|
||||
|
||||
@@ -327,13 +327,14 @@ Pour plus de détails, consultez le site officiel de VOICEVOX.</string>
|
||||
<string name="fix_request_message">Veuillez accorder la portée \'operator.read\' à mon jeton API actuel.</string>
|
||||
<string name="action_ask_ai">Demander à l\'IA de réparer</string>
|
||||
<string name="pairing_required_title">Couplage de périphériques requis</string>
|
||||
<string name="pairing_required_desc">Cet appareil n’est pas encore approuvé par le serveur. WakeHermesClaw essaiera d’abord de l’approuver via OpenClaw. Si ce n’est pas disponible, exécutez la commande sur l’hôte.</string>
|
||||
<string name="pairing_required_desc">Cet appareil n’est pas encore approuvé par le serveur. WakeHermesClaw essaiera de l’approuver automatiquement via l’endpoint de commande hôte du lien de configuration. Si ce n’est pas disponible, exécutez la commande sur l’hôte.</string>
|
||||
<string name="pairing_requested_scopes">Autorisations OpenClaw demandées : operator.read, operator.write, operator.admin, operator.pairing, operator.talk.secrets, operator.approvals.</string>
|
||||
<string name="pairing_copy_command">Copier la commande</string>
|
||||
<string name="pairing_command_copied">Commande copiée dans le presse-papiers</string>
|
||||
<string name="pairing_device_id">ID de l\'appareil : %s</string>
|
||||
<string name="pairing_approve_command">Approuver la commande (copie)</string>
|
||||
<string name="pairing_reject_command">Rejeter la commande (Copie)</string>
|
||||
<string name="pairing_host_command_required">Exécutez ceci sur l’hôte OpenClaw : %1$s</string>
|
||||
<string name="pairing_refresh_status">Actualiser l\'état</string>
|
||||
<string name="pairing_guide_title">Comment approuver cet appareil :</string>
|
||||
<string name="pairing_guide_step_1">1. Accédez au terminal de votre serveur OpenClaw.</string>
|
||||
|
||||
@@ -327,13 +327,14 @@
|
||||
<string name="fix_request_message">कृपया मेरे वर्तमान एपीआई टोकन को \'operator.read\' का दायरा प्रदान करें।</string>
|
||||
<string name="action_ask_ai">एआई को ठीक करने के लिए कहें</string>
|
||||
<string name="pairing_required_title">डिवाइस पेयरिंग आवश्यक है</string>
|
||||
<string name="pairing_required_desc">यह डिवाइस अभी तक सर्वर द्वारा स्वीकृत नहीं है. WakeHermesClaw पहले OpenClaw के जरिए इसे approve करने की कोशिश करेगा; अगर वह उपलब्ध न हो, तो host पर command चलाएँ.</string>
|
||||
<string name="pairing_required_desc">यह डिवाइस अभी तक सर्वर द्वारा स्वीकृत नहीं है. WakeHermesClaw setup link के host command endpoint से इसे अपने आप approve करने की कोशिश करेगा; अगर वह उपलब्ध न हो, तो host पर command चलाएँ.</string>
|
||||
<string name="pairing_requested_scopes">Requested OpenClaw scopes: operator.read, operator.write, operator.admin, operator.pairing, operator.talk.secrets, operator.approvals.</string>
|
||||
<string name="pairing_copy_command">कमांड कॉपी करें</string>
|
||||
<string name="pairing_command_copied">कमांड को क्लिपबोर्ड पर कॉपी किया गया</string>
|
||||
<string name="pairing_device_id">डिवाइस आईडी: %s</string>
|
||||
<string name="pairing_approve_command">आदेश स्वीकृत करें (कॉपी करें)</string>
|
||||
<string name="pairing_reject_command">आदेश अस्वीकार करें (कॉपी करें)</string>
|
||||
<string name="pairing_host_command_required">इसे OpenClaw host पर चलाएँ: %1$s</string>
|
||||
<string name="pairing_refresh_status">ताज़ा स्थिति</string>
|
||||
<string name="pairing_guide_title">इस डिवाइस को कैसे स्वीकृत करें:</string>
|
||||
<string name="pairing_guide_step_1">1. अपने OpenClaw सर्वर टर्मिनल तक पहुंचें।</string>
|
||||
|
||||
@@ -358,7 +358,7 @@
|
||||
<string name="fix_request_message">現在のAPIトークンに \'operator.read\' 権限を付与してください。</string>
|
||||
<string name="action_ask_ai">AIに修正を依頼</string>
|
||||
<string name="pairing_required_title">デバイスのペアリングが必要です</string>
|
||||
<string name="pairing_required_desc">このデバイスはまだサーバーで承認されていません。まず WakeHermesClaw が OpenClaw 経由で承認を試みます。使えない場合はホスト側でコマンドを実行してください。</string>
|
||||
<string name="pairing_required_desc">このデバイスはまだサーバーで承認されていません。WakeHermesClaw はセットアップリンクのホストコマンド経由で自動承認を試みます。使えない場合はホスト側でコマンドを実行してください。</string>
|
||||
<string name="pairing_requested_scopes">要求する OpenClaw 権限: operator.read, operator.write, operator.admin, operator.pairing, operator.talk.secrets, operator.approvals。</string>
|
||||
<string name="pairing_copy_command">コマンドをコピー</string>
|
||||
<string name="pairing_command_copied">コマンドをクリップボードにコピーしました</string>
|
||||
@@ -370,6 +370,7 @@
|
||||
<string name="pairing_gateway_auto_running">OpenClaw経由で自動承認しています...</string>
|
||||
<string name="pairing_gateway_approve_sent">ペアリングを承認しました。接続を更新しています...</string>
|
||||
<string name="pairing_gateway_failed">OpenClawでの承認に失敗しました。</string>
|
||||
<string name="pairing_host_command_required">OpenClaw ホストで実行してください: %1$s</string>
|
||||
<string name="pairing_terminal_running">Terminalで承認コマンドを実行中...</string>
|
||||
<string name="pairing_terminal_auto_running">Terminalに接続済みです。承認コマンドを自動実行しています...</string>
|
||||
<string name="pairing_terminal_approve_sent">承認コマンドを送信しました。接続を更新しています...</string>
|
||||
|
||||
@@ -327,13 +327,14 @@
|
||||
<string name="fix_request_message">Пожалуйста, предоставьте область действия \'operator.read\' для моего текущего токена API.</string>
|
||||
<string name="action_ask_ai">Попросите ИИ исправить</string>
|
||||
<string name="pairing_required_title">Требуется сопряжение устройств</string>
|
||||
<string name="pairing_required_desc">Это устройство еще не одобрено сервером. WakeHermesClaw сначала попробует одобрить его через OpenClaw; если это недоступно, выполните команду на хосте.</string>
|
||||
<string name="pairing_required_desc">Это устройство еще не одобрено сервером. WakeHermesClaw попробует автоматически одобрить его через хостовый командный endpoint из ссылки настройки; если это недоступно, выполните команду на хосте.</string>
|
||||
<string name="pairing_requested_scopes">Запрашиваемые права OpenClaw: operator.read, operator.write, operator.admin, operator.pairing, operator.talk.secrets, operator.approvals.</string>
|
||||
<string name="pairing_copy_command">Команда копирования</string>
|
||||
<string name="pairing_command_copied">Команда скопирована в буфер обмена</string>
|
||||
<string name="pairing_device_id">Идентификатор устройства: %s</string>
|
||||
<string name="pairing_approve_command">Утвердить команду (копировать)</string>
|
||||
<string name="pairing_reject_command">Отклонить команду (копировать)</string>
|
||||
<string name="pairing_host_command_required">Выполните на хосте OpenClaw: %1$s</string>
|
||||
<string name="pairing_refresh_status">Обновить статус</string>
|
||||
<string name="pairing_guide_title">Как одобрить это устройство:</string>
|
||||
<string name="pairing_guide_step_1">1. Получите доступ к серверному терминалу OpenClaw.</string>
|
||||
|
||||
@@ -327,13 +327,14 @@
|
||||
<string name="fix_request_message">请将 \'operator.read\' 范围授予我当前的 API 令牌。</string>
|
||||
<string name="action_ask_ai">请 AI 修复</string>
|
||||
<string name="pairing_required_title">需要设备配对</string>
|
||||
<string name="pairing_required_desc">此设备尚未获得服务器批准。WakeHermesClaw 会先尝试通过 OpenClaw 批准它;如果不可用,请在主机上运行该命令。</string>
|
||||
<string name="pairing_required_desc">此设备尚未获得服务器批准。WakeHermesClaw 会尝试通过设置链接中的主机命令端点自动批准它;如果不可用,请在主机上运行该命令。</string>
|
||||
<string name="pairing_requested_scopes">请求的 OpenClaw 权限:operator.read、operator.write、operator.admin、operator.pairing、operator.talk.secrets、operator.approvals。</string>
|
||||
<string name="pairing_copy_command">复制命令</string>
|
||||
<string name="pairing_command_copied">命令已复制到剪贴板</string>
|
||||
<string name="pairing_device_id">设备 ID:%s</string>
|
||||
<string name="pairing_approve_command">批准命令(副本)</string>
|
||||
<string name="pairing_reject_command">拒绝命令(复制)</string>
|
||||
<string name="pairing_host_command_required">在 OpenClaw 主机上运行:%1$s</string>
|
||||
<string name="pairing_refresh_status">刷新状态</string>
|
||||
<string name="pairing_guide_title">如何批准此设备:</string>
|
||||
<string name="pairing_guide_step_1">1。访问您的 OpenClaw 服务器终端。</string>
|
||||
|
||||
@@ -326,13 +326,14 @@
|
||||
<string name="fix_request_message">請將“operator.read”範圍授予我目前的 API 令牌。</string>
|
||||
<string name="action_ask_ai">請求 AI 修復</string>
|
||||
<string name="pairing_required_title">需要設備配對</string>
|
||||
<string name="pairing_required_desc">此裝置尚未獲得伺服器批准。WakeHermesClaw 會先嘗試透過 OpenClaw 批准它;如果不可用,請在主機上執行該命令。</string>
|
||||
<string name="pairing_required_desc">此裝置尚未獲得伺服器批准。WakeHermesClaw 會嘗試透過設定連結中的主機命令端點自動批准它;如果不可用,請在主機上執行該命令。</string>
|
||||
<string name="pairing_requested_scopes">要求的 OpenClaw 權限:operator.read、operator.write、operator.admin、operator.pairing、operator.talk.secrets、operator.approvals。</string>
|
||||
<string name="pairing_copy_command">複製指令</string>
|
||||
<string name="pairing_command_copied">命令已複製到剪貼簿</string>
|
||||
<string name="pairing_device_id">設備 ID:%s</string>
|
||||
<string name="pairing_approve_command">批准命令(副本)</string>
|
||||
<string name="pairing_reject_command">拒絕命令(複製)</string>
|
||||
<string name="pairing_host_command_required">在 OpenClaw 主機上執行:%1$s</string>
|
||||
<string name="pairing_refresh_status">刷新狀態</string>
|
||||
<string name="pairing_guide_title">如何批准該設備:</string>
|
||||
<string name="pairing_guide_step_1">1. 存取您的 OpenClaw 伺服器終端。</string>
|
||||
|
||||
@@ -593,7 +593,7 @@
|
||||
|
||||
<!-- Pairing -->
|
||||
<string name="pairing_required_title">Device Pairing Required</string>
|
||||
<string name="pairing_required_desc">This device is not yet approved by the server. WakeHermesClaw will try to approve it through OpenClaw first; if that is not available, run the command on the host.</string>
|
||||
<string name="pairing_required_desc">This device is not yet approved by the server. WakeHermesClaw will try to approve it through the host command endpoint in the setup link; if that is not available, run the command on the host.</string>
|
||||
<string name="pairing_requested_scopes">Requested OpenClaw scopes: operator.read, operator.write, operator.admin, operator.pairing, operator.talk.secrets, operator.approvals.</string>
|
||||
<string name="pairing_copy_command">Copy Command</string>
|
||||
<string name="pairing_command_copied">Command copied to clipboard</string>
|
||||
@@ -607,6 +607,7 @@
|
||||
<string name="pairing_gateway_auto_running">Approving through OpenClaw automatically...</string>
|
||||
<string name="pairing_gateway_approve_sent">Pairing approved. Refreshing connection...</string>
|
||||
<string name="pairing_gateway_failed">OpenClaw approval failed.</string>
|
||||
<string name="pairing_host_command_required">Run this on the OpenClaw host: %1$s</string>
|
||||
<string name="pairing_terminal_running">Running approval command in Terminal...</string>
|
||||
<string name="pairing_terminal_auto_running">Terminal is connected. Running approval command automatically...</string>
|
||||
<string name="pairing_terminal_approve_sent">Approval command sent. Refreshing connection...</string>
|
||||
|
||||
@@ -521,6 +521,7 @@ def start_terminal_command_server() -> Optional[dict]:
|
||||
r'''
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import urllib.parse
|
||||
@@ -530,6 +531,26 @@ from pathlib import Path
|
||||
port = int(sys.argv[1])
|
||||
secret = sys.argv[2]
|
||||
|
||||
def run_command(command, timeout):
|
||||
return subprocess.run(
|
||||
command,
|
||||
shell=True,
|
||||
cwd=str(Path.home()),
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=timeout,
|
||||
executable=os.environ.get("SHELL") or "/bin/zsh",
|
||||
)
|
||||
|
||||
def resolve_openclaw_latest_approval(command, proc, timeout):
|
||||
if command != "openclaw devices approve --latest" or proc.returncode == 0:
|
||||
return proc
|
||||
combined = (proc.stdout or "") + "\n" + (proc.stderr or "")
|
||||
match = re.search(r"openclaw\s+devices\s+approve\s+([0-9a-fA-F-]{36})(?:\s+--json)?", combined)
|
||||
if not match:
|
||||
return proc
|
||||
return run_command(f"openclaw devices approve {match.group(1)}", timeout)
|
||||
|
||||
class TerminalHandler(BaseHTTPRequestHandler):
|
||||
server_version = "AgentVoiceTerminal/1"
|
||||
|
||||
@@ -569,15 +590,8 @@ class TerminalHandler(BaseHTTPRequestHandler):
|
||||
timeout = int(body.get("timeoutSeconds") or 30)
|
||||
timeout = max(1, min(timeout, 120))
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
command,
|
||||
shell=True,
|
||||
cwd=str(Path.home()),
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=timeout,
|
||||
executable=os.environ.get("SHELL") or "/bin/zsh",
|
||||
)
|
||||
proc = run_command(command, timeout)
|
||||
proc = resolve_openclaw_latest_approval(command, proc, timeout)
|
||||
except subprocess.TimeoutExpired:
|
||||
self._json(504, {"ok": False, "error": "timeout"})
|
||||
return
|
||||
@@ -1621,6 +1635,15 @@ def main(argv: Optional[List[str]] = None) -> int:
|
||||
)
|
||||
if not mux_public_url and include_openclaw and openclaw_port_open:
|
||||
openclaw_public_url = start_public_tunnel("http://127.0.0.1:18789", "openclaw", args.tunnel_provider)
|
||||
if not mux_public_url and terminal_command_pairing and terminal_command_pairing.get("port"):
|
||||
terminal_public_url = start_public_tunnel(
|
||||
f"http://127.0.0.1:{terminal_command_pairing['port']}",
|
||||
"agentvoice-terminal",
|
||||
args.tunnel_provider,
|
||||
)
|
||||
if terminal_public_url:
|
||||
terminal_command_pairing = dict(terminal_command_pairing)
|
||||
terminal_command_pairing["url"] = terminal_public_url.rstrip("/") + "/run"
|
||||
if openclaw_public_url:
|
||||
configure_openclaw_allowed_origin(openclaw_public_url)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user