clawdex-mobile 5.0.7 → 5.0.8
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/package.json +4 -1
- package/scripts/setup-wizard.sh +51 -15
- package/scripts/start-bridge-secure.js +120 -62
- package/scripts/stop-services.sh +22 -0
- package/services/rust-bridge/Cargo.lock +1 -1
- package/services/rust-bridge/Cargo.toml +1 -1
- package/vendor/bridge-binaries/darwin-arm64/codex-rust-bridge +0 -0
- package/vendor/bridge-binaries/darwin-x64/codex-rust-bridge +0 -0
- package/vendor/bridge-binaries/linux-arm64/codex-rust-bridge +0 -0
- package/vendor/bridge-binaries/linux-armv7l/codex-rust-bridge +0 -0
- package/vendor/bridge-binaries/linux-x64/codex-rust-bridge +0 -0
- package/vendor/bridge-binaries/win32-x64/codex-rust-bridge.exe +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clawdex-mobile",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.8",
|
|
4
4
|
"description": "Private-network mobile bridge and CLI for Codex and OpenCode",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"codex",
|
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
"publishConfig": {
|
|
20
20
|
"access": "public"
|
|
21
21
|
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"qrcode-terminal": "^0.12.0"
|
|
24
|
+
},
|
|
22
25
|
"bin": {
|
|
23
26
|
"clawdex": "./bin/clawdex.js"
|
|
24
27
|
},
|
package/scripts/setup-wizard.sh
CHANGED
|
@@ -194,7 +194,7 @@ sync_active_engine_from_selection() {
|
|
|
194
194
|
return
|
|
195
195
|
fi
|
|
196
196
|
|
|
197
|
-
if
|
|
197
|
+
if selected_engines_contains "$ACTIVE_ENGINE"; then
|
|
198
198
|
return
|
|
199
199
|
fi
|
|
200
200
|
|
|
@@ -215,6 +215,30 @@ format_engine_list() {
|
|
|
215
215
|
printf '%s' "$result"
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
selected_engines_contains() {
|
|
219
|
+
local needle="$1"
|
|
220
|
+
|
|
221
|
+
if (( ${#SELECTED_ENGINES[@]} == 0 )); then
|
|
222
|
+
return 1
|
|
223
|
+
fi
|
|
224
|
+
|
|
225
|
+
engine_list_contains "$needle" "${SELECTED_ENGINES[@]}"
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
format_selected_engines() {
|
|
229
|
+
if (( ${#SELECTED_ENGINES[@]} == 0 )); then
|
|
230
|
+
printf ''
|
|
231
|
+
return 0
|
|
232
|
+
fi
|
|
233
|
+
|
|
234
|
+
format_engine_list "${SELECTED_ENGINES[@]}"
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
selected_engines_csv() {
|
|
238
|
+
local IFS=','
|
|
239
|
+
printf '%s' "${SELECTED_ENGINES[*]-}"
|
|
240
|
+
}
|
|
241
|
+
|
|
218
242
|
engine_from_menu_label() {
|
|
219
243
|
case "$1" in
|
|
220
244
|
"Codex")
|
|
@@ -957,7 +981,11 @@ print_existing_setup_summary() {
|
|
|
957
981
|
local harnesses=""
|
|
958
982
|
local source_path=""
|
|
959
983
|
local saved_active_engine="$ACTIVE_ENGINE"
|
|
960
|
-
local -a saved_selected_engines=(
|
|
984
|
+
local -a saved_selected_engines=()
|
|
985
|
+
|
|
986
|
+
if (( ${#SELECTED_ENGINES[@]} > 0 )); then
|
|
987
|
+
saved_selected_engines=("${SELECTED_ENGINES[@]}")
|
|
988
|
+
fi
|
|
961
989
|
|
|
962
990
|
if [[ ! -f "$SECURE_ENV_FILE" ]]; then
|
|
963
991
|
return 1
|
|
@@ -971,7 +999,7 @@ print_existing_setup_summary() {
|
|
|
971
999
|
if [[ -n "$harnesses" ]] && ! parse_existing_engine_list_csv "$harnesses"; then
|
|
972
1000
|
harnesses=""
|
|
973
1001
|
elif [[ -n "$harnesses" ]]; then
|
|
974
|
-
harnesses="$(
|
|
1002
|
+
harnesses="$(selected_engines_csv)"
|
|
975
1003
|
fi
|
|
976
1004
|
if [[ -z "$harnesses" ]]; then
|
|
977
1005
|
harnesses="$(extract_env_value "$SECURE_ENV_FILE" "BRIDGE_ACTIVE_ENGINE")"
|
|
@@ -999,7 +1027,10 @@ print_existing_setup_summary() {
|
|
|
999
1027
|
fi
|
|
1000
1028
|
echo "source: $source_path"
|
|
1001
1029
|
|
|
1002
|
-
SELECTED_ENGINES=(
|
|
1030
|
+
SELECTED_ENGINES=()
|
|
1031
|
+
if (( ${#saved_selected_engines[@]} > 0 )); then
|
|
1032
|
+
SELECTED_ENGINES=("${saved_selected_engines[@]}")
|
|
1033
|
+
fi
|
|
1003
1034
|
ACTIVE_ENGINE="$saved_active_engine"
|
|
1004
1035
|
}
|
|
1005
1036
|
|
|
@@ -1082,12 +1113,12 @@ choose_bridge_network_mode() {
|
|
|
1082
1113
|
choose_runtime_engine() {
|
|
1083
1114
|
local label=""
|
|
1084
1115
|
MENU_MULTI_PRESELECTED="Codex"
|
|
1085
|
-
if
|
|
1116
|
+
if selected_engines_contains "codex"; then
|
|
1086
1117
|
MENU_MULTI_PRESELECTED="Codex"
|
|
1087
1118
|
else
|
|
1088
1119
|
MENU_MULTI_PRESELECTED=""
|
|
1089
1120
|
fi
|
|
1090
|
-
if
|
|
1121
|
+
if selected_engines_contains "opencode"; then
|
|
1091
1122
|
if [[ -n "$MENU_MULTI_PRESELECTED" ]]; then
|
|
1092
1123
|
MENU_MULTI_PRESELECTED+=","
|
|
1093
1124
|
fi
|
|
@@ -1101,7 +1132,7 @@ choose_runtime_engine() {
|
|
|
1101
1132
|
SELECTED_ENGINES+=("$(engine_from_menu_label "$label")")
|
|
1102
1133
|
done
|
|
1103
1134
|
sync_active_engine_from_selection
|
|
1104
|
-
info "Selected harnesses: $(
|
|
1135
|
+
info "Selected harnesses: $(format_selected_engines)."
|
|
1105
1136
|
}
|
|
1106
1137
|
|
|
1107
1138
|
infer_network_mode_from_host() {
|
|
@@ -1217,6 +1248,11 @@ ensure_opencode_cli() {
|
|
|
1217
1248
|
|
|
1218
1249
|
ensure_selected_engine_clis() {
|
|
1219
1250
|
local engine=""
|
|
1251
|
+
|
|
1252
|
+
if (( ${#SELECTED_ENGINES[@]} == 0 )); then
|
|
1253
|
+
abort_wizard "Select at least one harness before continuing."
|
|
1254
|
+
fi
|
|
1255
|
+
|
|
1220
1256
|
for engine in "${SELECTED_ENGINES[@]}"; do
|
|
1221
1257
|
case "$engine" in
|
|
1222
1258
|
codex)
|
|
@@ -1613,16 +1649,16 @@ fi
|
|
|
1613
1649
|
load_existing_engine_selection
|
|
1614
1650
|
if [[ "$CONFIG_ACTION" == "keep" ]]; then
|
|
1615
1651
|
if [[ "$ENGINE_SELECTION_PRESET" == "false" ]]; then
|
|
1616
|
-
info "Keeping existing harnesses: $(
|
|
1652
|
+
info "Keeping existing harnesses: $(format_selected_engines)."
|
|
1617
1653
|
else
|
|
1618
|
-
info "Harness selection preset via flag: $(
|
|
1654
|
+
info "Harness selection preset via flag: $(format_selected_engines)."
|
|
1619
1655
|
fi
|
|
1620
1656
|
else
|
|
1621
1657
|
section "Harnesses"
|
|
1622
1658
|
if [[ "$ENGINE_SELECTION_PRESET" == "false" ]]; then
|
|
1623
1659
|
choose_runtime_engine
|
|
1624
1660
|
else
|
|
1625
|
-
info "Harness selection preset via flag: $(
|
|
1661
|
+
info "Harness selection preset via flag: $(format_selected_engines)."
|
|
1626
1662
|
fi
|
|
1627
1663
|
fi
|
|
1628
1664
|
|
|
@@ -1652,7 +1688,7 @@ if [[ "$CONFIG_ACTION" != "keep" ]]; then
|
|
|
1652
1688
|
esac
|
|
1653
1689
|
|
|
1654
1690
|
section "Write secure config"
|
|
1655
|
-
BRIDGE_NETWORK_MODE="$NETWORK_MODE" BRIDGE_HOST_OVERRIDE="$BRIDGE_HOST" BRIDGE_ACTIVE_ENGINE="$ACTIVE_ENGINE" BRIDGE_ENABLED_ENGINES="$(
|
|
1691
|
+
BRIDGE_NETWORK_MODE="$NETWORK_MODE" BRIDGE_HOST_OVERRIDE="$BRIDGE_HOST" BRIDGE_ACTIVE_ENGINE="$ACTIVE_ENGINE" BRIDGE_ENABLED_ENGINES="$(selected_engines_csv)" "$SCRIPT_DIR/setup-secure-dev.sh"
|
|
1656
1692
|
else
|
|
1657
1693
|
ok "Keeping existing secure config."
|
|
1658
1694
|
NETWORK_MODE="$(extract_env_value "$SECURE_ENV_FILE" "BRIDGE_NETWORK_MODE")"
|
|
@@ -1677,10 +1713,10 @@ else
|
|
|
1677
1713
|
fi
|
|
1678
1714
|
|
|
1679
1715
|
section "Write secure config"
|
|
1680
|
-
BRIDGE_NETWORK_MODE="$NETWORK_MODE" BRIDGE_HOST_OVERRIDE="$BRIDGE_HOST" BRIDGE_ACTIVE_ENGINE="$ACTIVE_ENGINE" BRIDGE_ENABLED_ENGINES="$(
|
|
1681
|
-
elif [[ "$(extract_env_value "$SECURE_ENV_FILE" "BRIDGE_ENABLED_ENGINES")" != "$(
|
|
1716
|
+
BRIDGE_NETWORK_MODE="$NETWORK_MODE" BRIDGE_HOST_OVERRIDE="$BRIDGE_HOST" BRIDGE_ACTIVE_ENGINE="$ACTIVE_ENGINE" BRIDGE_ENABLED_ENGINES="$(selected_engines_csv)" "$SCRIPT_DIR/setup-secure-dev.sh"
|
|
1717
|
+
elif [[ "$(extract_env_value "$SECURE_ENV_FILE" "BRIDGE_ENABLED_ENGINES")" != "$(selected_engines_csv)" ]]; then
|
|
1682
1718
|
section "Write secure config"
|
|
1683
|
-
BRIDGE_NETWORK_MODE="$NETWORK_MODE" BRIDGE_HOST_OVERRIDE="$BRIDGE_HOST" BRIDGE_ACTIVE_ENGINE="$ACTIVE_ENGINE" BRIDGE_ENABLED_ENGINES="$(
|
|
1719
|
+
BRIDGE_NETWORK_MODE="$NETWORK_MODE" BRIDGE_HOST_OVERRIDE="$BRIDGE_HOST" BRIDGE_ACTIVE_ENGINE="$ACTIVE_ENGINE" BRIDGE_ENABLED_ENGINES="$(selected_engines_csv)" "$SCRIPT_DIR/setup-secure-dev.sh"
|
|
1684
1720
|
fi
|
|
1685
1721
|
fi
|
|
1686
1722
|
|
|
@@ -1711,7 +1747,7 @@ BRIDGE_PORT="${BRIDGE_PORT:-8787}"
|
|
|
1711
1747
|
section "Summary"
|
|
1712
1748
|
rail_echo "Bridge mode: $NETWORK_MODE"
|
|
1713
1749
|
rail_echo "Bridge endpoint: http://$BRIDGE_HOST:$BRIDGE_PORT"
|
|
1714
|
-
rail_echo "Harnesses: $(
|
|
1750
|
+
rail_echo "Harnesses: $(format_selected_engines)"
|
|
1715
1751
|
rail_echo "Secure env: $SECURE_ENV_FILE"
|
|
1716
1752
|
if [[ "$FLOW" == "quickstart" ]]; then
|
|
1717
1753
|
rail_echo "${DIM}Tip: re-run with Manual mode for full control at each step.${RESET}"
|
|
@@ -17,6 +17,10 @@ const {
|
|
|
17
17
|
|
|
18
18
|
const DEFAULT_HEALTH_TIMEOUT_MS = 15000;
|
|
19
19
|
const DEV_HEALTH_TIMEOUT_MS = 60000;
|
|
20
|
+
let qrcodeTerminal = null;
|
|
21
|
+
let qrcodeTerminalLoaded = false;
|
|
22
|
+
let qrcodeTerminalLoadError = null;
|
|
23
|
+
let pairingQrRenderError = null;
|
|
20
24
|
|
|
21
25
|
function resolveRootDir() {
|
|
22
26
|
let rootDir = process.env.INIT_CWD ? path.resolve(process.env.INIT_CWD) : path.resolve(__dirname, "..");
|
|
@@ -75,88 +79,144 @@ function buildBridgeUrl(host, port) {
|
|
|
75
79
|
return `http://${formatHostForUrl(host)}:${port}`;
|
|
76
80
|
}
|
|
77
81
|
|
|
78
|
-
function
|
|
79
|
-
const
|
|
80
|
-
return
|
|
82
|
+
function isUnspecifiedBindHost(host) {
|
|
83
|
+
const normalized = String(host || "").trim().toLowerCase();
|
|
84
|
+
return normalized === "0.0.0.0" || normalized === "::" || normalized === "[::]";
|
|
81
85
|
}
|
|
82
86
|
|
|
83
|
-
function
|
|
84
|
-
const bridgeUrl = buildBridgeUrl(endpoint.host, endpoint.port);
|
|
85
|
-
console.log(`Bridge URL: ${bridgeUrl}`);
|
|
86
|
-
|
|
87
|
+
function buildPairingPayload(env, endpoint) {
|
|
87
88
|
const token = readNonEmptyEnv(env, "BRIDGE_AUTH_TOKEN");
|
|
88
|
-
if (token) {
|
|
89
|
-
|
|
89
|
+
if (!token || isUnspecifiedBindHost(endpoint.host)) {
|
|
90
|
+
return null;
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
return
|
|
93
|
+
return JSON.stringify({
|
|
94
|
+
type: "clawdex-bridge-pair",
|
|
95
|
+
bridgeUrl: buildBridgeUrl(endpoint.host, endpoint.port),
|
|
96
|
+
bridgeToken: token,
|
|
97
|
+
});
|
|
93
98
|
}
|
|
94
99
|
|
|
95
|
-
function
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
function buildTokenOnlyPairingPayload(env) {
|
|
101
|
+
const token = readNonEmptyEnv(env, "BRIDGE_AUTH_TOKEN");
|
|
102
|
+
if (!token) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
98
105
|
|
|
99
|
-
|
|
100
|
-
|
|
106
|
+
return JSON.stringify({
|
|
107
|
+
type: "clawdex-bridge-token",
|
|
108
|
+
bridgeToken: token,
|
|
109
|
+
});
|
|
101
110
|
}
|
|
102
111
|
|
|
103
|
-
function
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (line.includes("Bridge pairing QR (scan from mobile onboarding):")) {
|
|
108
|
-
const endIndex = lines.findIndex(
|
|
109
|
-
(entry, offset) =>
|
|
110
|
-
offset > index && entry.includes("QR contains bridge URL + token for one-tap onboarding.")
|
|
111
|
-
);
|
|
112
|
-
if (endIndex !== -1) {
|
|
113
|
-
return lines.slice(index, endIndex + 1).join("\n").trimEnd();
|
|
114
|
-
}
|
|
115
|
-
}
|
|
112
|
+
function loadQrcodeTerminal() {
|
|
113
|
+
if (qrcodeTerminalLoaded) {
|
|
114
|
+
return qrcodeTerminal;
|
|
115
|
+
}
|
|
116
116
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (endIndex !== -1) {
|
|
124
|
-
return lines.slice(index, endIndex + 1).join("\n").trimEnd();
|
|
125
|
-
}
|
|
126
|
-
}
|
|
117
|
+
qrcodeTerminalLoaded = true;
|
|
118
|
+
try {
|
|
119
|
+
qrcodeTerminal = require("qrcode-terminal");
|
|
120
|
+
} catch (error) {
|
|
121
|
+
qrcodeTerminal = null;
|
|
122
|
+
qrcodeTerminalLoadError = error;
|
|
127
123
|
}
|
|
128
124
|
|
|
129
|
-
return
|
|
125
|
+
return qrcodeTerminal;
|
|
130
126
|
}
|
|
131
127
|
|
|
132
|
-
function
|
|
128
|
+
function printPairingQr(env, endpoint) {
|
|
129
|
+
pairingQrRenderError = null;
|
|
130
|
+
const qr = loadQrcodeTerminal();
|
|
131
|
+
if (!qr) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
|
|
133
135
|
try {
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
const payload = buildPairingPayload(env, endpoint);
|
|
137
|
+
if (payload) {
|
|
138
|
+
console.log("");
|
|
139
|
+
console.log("Bridge pairing QR (scan from mobile onboarding):");
|
|
140
|
+
qr.generate(payload, { small: true });
|
|
141
|
+
console.log("QR contains bridge URL + token for one-tap onboarding.");
|
|
142
|
+
console.log("");
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const tokenPayload = buildTokenOnlyPairingPayload(env);
|
|
147
|
+
if (!tokenPayload) {
|
|
138
148
|
return false;
|
|
139
149
|
}
|
|
150
|
+
|
|
140
151
|
console.log("");
|
|
141
|
-
console.log(
|
|
152
|
+
console.log("Bridge token QR fallback (scan from mobile onboarding):");
|
|
153
|
+
qr.generate(tokenPayload, { small: true });
|
|
154
|
+
console.log(
|
|
155
|
+
`Full pairing QR unavailable because BRIDGE_HOST=${endpoint.host} is a bind address. Enter URL manually in onboarding.`
|
|
156
|
+
);
|
|
142
157
|
console.log("");
|
|
143
158
|
return true;
|
|
144
|
-
} catch {
|
|
159
|
+
} catch (error) {
|
|
160
|
+
pairingQrRenderError = error;
|
|
145
161
|
return false;
|
|
146
162
|
}
|
|
147
163
|
}
|
|
148
164
|
|
|
149
|
-
|
|
150
|
-
const
|
|
165
|
+
function printPairingQrUnavailableMessage(env) {
|
|
166
|
+
const token = readNonEmptyEnv(env, "BRIDGE_AUTH_TOKEN");
|
|
167
|
+
if (!token) {
|
|
168
|
+
console.log(
|
|
169
|
+
"Pairing QR unavailable because BRIDGE_AUTH_TOKEN is not set. Bridge URL is above for manual onboarding."
|
|
170
|
+
);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
151
173
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
174
|
+
if (pairingQrRenderError) {
|
|
175
|
+
console.log(
|
|
176
|
+
`Pairing QR unavailable because terminal rendering failed: ${pairingQrRenderError.message}. Bridge URL/token are above for manual onboarding.`
|
|
177
|
+
);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (qrcodeTerminalLoaded && !qrcodeTerminal) {
|
|
182
|
+
const detail =
|
|
183
|
+
qrcodeTerminalLoadError && qrcodeTerminalLoadError.message
|
|
184
|
+
? ` (${qrcodeTerminalLoadError.message})`
|
|
185
|
+
: "";
|
|
186
|
+
console.log(
|
|
187
|
+
`Pairing QR unavailable because the terminal QR renderer could not be loaded${detail}. Bridge URL/token are above for manual onboarding.`
|
|
188
|
+
);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
console.log(
|
|
193
|
+
"Pairing QR unavailable due to an unexpected startup condition. Bridge URL/token are above for manual onboarding."
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function shouldShowPairingQr(env) {
|
|
198
|
+
const raw = readNonEmptyEnv(env, "BRIDGE_SHOW_PAIRING_QR");
|
|
199
|
+
return raw ? raw.toLowerCase() !== "false" : true;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function printBridgeAccessDetails(env, endpoint) {
|
|
203
|
+
const bridgeUrl = buildBridgeUrl(endpoint.host, endpoint.port);
|
|
204
|
+
console.log(`Bridge URL: ${bridgeUrl}`);
|
|
205
|
+
|
|
206
|
+
const token = readNonEmptyEnv(env, "BRIDGE_AUTH_TOKEN");
|
|
207
|
+
if (token) {
|
|
208
|
+
console.log(`Bridge token: ${token}`);
|
|
157
209
|
}
|
|
158
210
|
|
|
159
|
-
return
|
|
211
|
+
return bridgeUrl;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function bridgePidFile(rootDir) {
|
|
215
|
+
return path.join(rootDir, ".bridge.pid");
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function bridgeLogFile(rootDir) {
|
|
219
|
+
return path.join(rootDir, ".bridge.log");
|
|
160
220
|
}
|
|
161
221
|
|
|
162
222
|
function readPidFile(rootDir) {
|
|
@@ -344,9 +404,10 @@ async function spawnDetachedAndWait(command, args, options) {
|
|
|
344
404
|
console.log(`Bridge already running (pid ${existingPid}).`);
|
|
345
405
|
console.log(`Logs: ${logPath}`);
|
|
346
406
|
console.log("Bridge is healthy.");
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
407
|
+
const endpoint = { host, port };
|
|
408
|
+
printBridgeAccessDetails(env, endpoint);
|
|
409
|
+
if (shouldShowPairingQr(env) && !printPairingQr(env, endpoint)) {
|
|
410
|
+
printPairingQrUnavailableMessage(env);
|
|
350
411
|
}
|
|
351
412
|
return;
|
|
352
413
|
}
|
|
@@ -363,7 +424,6 @@ async function spawnDetachedAndWait(command, args, options) {
|
|
|
363
424
|
|
|
364
425
|
const output = fs.openSync(logPath, "a");
|
|
365
426
|
const error = fs.openSync(logPath, "a");
|
|
366
|
-
const logStartOffset = fs.existsSync(logPath) ? fs.statSync(logPath).size : 0;
|
|
367
427
|
|
|
368
428
|
const child = spawn(command, args, {
|
|
369
429
|
cwd,
|
|
@@ -394,10 +454,8 @@ async function spawnDetachedAndWait(command, args, options) {
|
|
|
394
454
|
console.log("Bridge is healthy.");
|
|
395
455
|
printBridgeAccessDetails(env, endpoint);
|
|
396
456
|
|
|
397
|
-
if (shouldShowPairingQr(env) && !(
|
|
398
|
-
|
|
399
|
-
"Pairing QR not found in the new bridge startup log. Bridge URL/token are above. Open logs if you need to inspect startup output."
|
|
400
|
-
);
|
|
457
|
+
if (shouldShowPairingQr(env) && !printPairingQr(env, endpoint)) {
|
|
458
|
+
printPairingQrUnavailableMessage(env);
|
|
401
459
|
}
|
|
402
460
|
} catch (error) {
|
|
403
461
|
removePidFile(rootDir);
|
package/scripts/stop-services.sh
CHANGED
|
@@ -73,6 +73,23 @@ extract_env_value() {
|
|
|
73
73
|
' "$file"
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
stop_launchctl_job() {
|
|
77
|
+
local label="$1"
|
|
78
|
+
|
|
79
|
+
if [[ -z "$label" ]] || ! command -v launchctl >/dev/null 2>&1; then
|
|
80
|
+
return 1
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
local domain="gui/$(id -u)/$label"
|
|
84
|
+
if ! launchctl print "$domain" >/dev/null 2>&1; then
|
|
85
|
+
return 1
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
echo "Stopping launchd job: $label"
|
|
89
|
+
launchctl bootout "$domain" >/dev/null 2>&1 || launchctl remove "$label" >/dev/null 2>&1 || true
|
|
90
|
+
return 0
|
|
91
|
+
}
|
|
92
|
+
|
|
76
93
|
stop_process_group() {
|
|
77
94
|
local label="$1"
|
|
78
95
|
local pattern="$2"
|
|
@@ -111,7 +128,12 @@ stop_process_group() {
|
|
|
111
128
|
|
|
112
129
|
echo "Stopping Clawdex services for project: $ROOT_DIR"
|
|
113
130
|
|
|
131
|
+
BRIDGE_PORT="${BRIDGE_PORT:-$(extract_env_value "$SECURE_ENV_FILE" "BRIDGE_PORT" || true)}"
|
|
132
|
+
BRIDGE_PORT="${BRIDGE_PORT:-8787}"
|
|
133
|
+
|
|
114
134
|
stop_process_group "Expo" "$ROOT_DIR/.*/expo start|$ROOT_DIR/node_modules/.bin/expo start"
|
|
135
|
+
stop_launchctl_job "clawdex.bridge.$BRIDGE_PORT" || true
|
|
136
|
+
stop_process_group "Bridge launcher" "$ROOT_DIR/scripts/start-bridge-secure\\.js|node .*start-bridge-secure\\.js"
|
|
115
137
|
stop_pid_file_process "Rust bridge" "$BRIDGE_PID_FILE" || true
|
|
116
138
|
stop_process_group "Rust bridge" "$ROOT_DIR/services/rust-bridge|codex-rust-bridge|@codex/rust-bridge"
|
|
117
139
|
stop_process_group "Legacy TS bridge" "$ROOT_DIR/services/mac-bridge|@codex/mac-bridge"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|