@matelink/cli 2026.4.7 → 2026.4.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/bin/matecli.mjs +298 -101
- package/package.json +1 -1
package/bin/matecli.mjs
CHANGED
|
@@ -30,13 +30,205 @@ const CLI_COMMAND_NAME = "matecli";
|
|
|
30
30
|
// compatibility endpoints remain available without per-method scope juggling.
|
|
31
31
|
const DEFAULT_GATEWAY_SCOPES = "operator.admin";
|
|
32
32
|
const CLI_ENTRY = fileURLToPath(import.meta.url);
|
|
33
|
+
const CLI_LANGUAGE = detectCliLanguage();
|
|
34
|
+
const CLI_I18N = {
|
|
35
|
+
zh: {
|
|
36
|
+
help_title: `${CLI_COMMAND_NAME} CLI`,
|
|
37
|
+
help_usage: "用法:",
|
|
38
|
+
help_environment: "环境变量:",
|
|
39
|
+
help_package: `包名: ${CLI_PACKAGE_NAME}`,
|
|
40
|
+
help_tip: "提示:",
|
|
41
|
+
help_tip_pair: " pair 命令会自动以后台模式启动 relay bridge worker。",
|
|
42
|
+
help_tip_no_serve: " 如果不希望自动启动 bridge worker,可使用 --no-serve-relay。",
|
|
43
|
+
help_env_home: " OPENCLAW_HOME 覆盖 OpenClaw 主目录(默认: ~/.openclaw)",
|
|
44
|
+
help_env_openim: " OPENIM_RELAY_URL / OPENIM_RELAY_TOKEN",
|
|
45
|
+
help_env_relay_url: ` TESTNEXTIM_RELAY_URL 覆盖 relay 地址(默认: ${DEFAULT_RELAY_URL})`,
|
|
46
|
+
help_env_relay_token: " TESTNEXTIM_RELAY_TOKEN 用于 pair publish/bind 接口的 Bearer Token",
|
|
47
|
+
help_env_gateway_base:
|
|
48
|
+
" OPENCLAW_TESTNEXTIM_GATEWAY_BASE_URL 本地 gateway 地址(优先于 openclaw.json 中的 gateway.port)",
|
|
49
|
+
help_env_gateway_port:
|
|
50
|
+
" OPENCLAW_GATEWAY_PORT / OPENCLAW_GATEWAY_HOST 可显式覆盖本地 gateway host/port",
|
|
51
|
+
config_read_failed: "无法读取配置文件: {path}",
|
|
52
|
+
config_invalid_json: "配置文件 JSON 格式无效: {path}",
|
|
53
|
+
fail_prefix: CLI_COMMAND_NAME,
|
|
54
|
+
pair_usage_missing: `配对码不能为空。用法: ${CLI_COMMAND_NAME} pair <1234|123456|XXXX-XXXX>`,
|
|
55
|
+
relay_url_required: "缺少 relay 地址。",
|
|
56
|
+
relay_url_missing_detail: "已启用 relay,但当前没有可用的 URL。",
|
|
57
|
+
relay_url_hint: `可直接使用内置默认值(${DEFAULT_RELAY_URL}),或通过 --relay / TESTNEXTIM_RELAY_URL 传入。`,
|
|
58
|
+
pair_code_not_found: "配对码不存在: {code}",
|
|
59
|
+
pair_code_generate_in_app: "请先在手机 App 里生成新的配对码。",
|
|
60
|
+
pair_code_consumed: "这个配对码已经被使用过了: {code}",
|
|
61
|
+
pair_missing_client_user_id: "这个配对码缺少客户端标识。",
|
|
62
|
+
pair_regenerate_latest: "请在 App 里重新生成最新的配对码后再试一次。",
|
|
63
|
+
bound_host_exists: "这台主机已经绑定过设备。",
|
|
64
|
+
current_client_user_id: "当前 clientUserId: {value}",
|
|
65
|
+
active_pair_code: "当前配对码: {value}",
|
|
66
|
+
reset_first: `请先执行 \`${CLI_COMMAND_NAME} reset\` 清掉当前绑定,再重新配对。`,
|
|
67
|
+
binding_cleared: "已清除绑定: {value}",
|
|
68
|
+
restart_failed_after_config: "更新配置后,OpenClaw 重启失败。",
|
|
69
|
+
restart_manual_retry: "请手动执行 `openclaw daemon restart` 后重试。",
|
|
70
|
+
gateway_not_ready: "本地 OpenClaw 网关 `/v1/responses` 还没有准备好。",
|
|
71
|
+
gateway_checked: "检查地址: {url}",
|
|
72
|
+
gateway_http_expected: "HTTP {status}(预期不是 401/403/404)",
|
|
73
|
+
gateway_request_failed: "{error}",
|
|
74
|
+
gateway_ready_hint: "请确认 OpenClaw daemon 正在运行,并且 responses endpoint 已启用。",
|
|
75
|
+
pair_success: "配对已就绪,请回到 App 完成确认。",
|
|
76
|
+
pair_worker_failed: "配对初始化失败,relay bridge worker 启动失败。",
|
|
77
|
+
setup_updated: "配置已更新: {path}",
|
|
78
|
+
setup_ready: "配置已准备好: {path}",
|
|
79
|
+
setup_state_file: "状态文件: {path}",
|
|
80
|
+
setup_transport: "聊天传输模式: {mode}",
|
|
81
|
+
setup_restarted: "OpenClaw 已重启。",
|
|
82
|
+
setup_restart_failed: "OpenClaw 重启失败,请手动执行:",
|
|
83
|
+
no_active_binding: "当前没有可清除的绑定。",
|
|
84
|
+
relay_reset_done: "Relay 绑定已重置。",
|
|
85
|
+
relay_reset_empty: "Relay 上没有可清除的绑定。",
|
|
86
|
+
relay_reset_skipped: "已跳过 Relay 绑定重置。",
|
|
87
|
+
stopped_bridge_count: "已停止 {count} 个 bridge 进程。",
|
|
88
|
+
local_state_reset: "本地状态已重置: {path}",
|
|
89
|
+
reset_ready: `现在可以重新执行 \`${CLI_COMMAND_NAME} pair <code>\`。`,
|
|
90
|
+
status_config: "配置文件: {value}",
|
|
91
|
+
status_channel: "通道: {value}",
|
|
92
|
+
status_enabled: "启用: {value}",
|
|
93
|
+
status_bind_base: "绑定地址: {value}",
|
|
94
|
+
status_relay_url: "Relay 地址: {value}",
|
|
95
|
+
status_transport: "传输模式: {value}",
|
|
96
|
+
status_gateway_base: "本地 Gateway: {value}",
|
|
97
|
+
status_webhook_path: "Webhook 路径: {value}",
|
|
98
|
+
status_bind_path: "Bind 路径: {value}",
|
|
99
|
+
status_gateway_id: "Relay Gateway ID: {value}",
|
|
100
|
+
status_client_token: "Relay Client Token: {value}",
|
|
101
|
+
status_gateway_token: "Relay Gateway Token: {value}",
|
|
102
|
+
status_app_secret: "App Secret: {value}",
|
|
103
|
+
status_access_token: "Access Token: {value}",
|
|
104
|
+
status_linked_user: "已绑定用户: {value}",
|
|
105
|
+
yes: "是",
|
|
106
|
+
no: "否",
|
|
107
|
+
set: "已设置",
|
|
108
|
+
missing: "缺失",
|
|
109
|
+
not_set: "未设置",
|
|
110
|
+
not_linked: "未绑定",
|
|
111
|
+
},
|
|
112
|
+
en: {
|
|
113
|
+
help_title: `${CLI_COMMAND_NAME} CLI`,
|
|
114
|
+
help_usage: "Usage:",
|
|
115
|
+
help_environment: "Environment:",
|
|
116
|
+
help_package: `Package: ${CLI_PACKAGE_NAME}`,
|
|
117
|
+
help_tip: "Tip:",
|
|
118
|
+
help_tip_pair: " The pair command auto-starts the relay bridge worker in detached mode.",
|
|
119
|
+
help_tip_no_serve: " Use --no-serve-relay if you do not want the bridge worker to start automatically.",
|
|
120
|
+
help_env_home: " OPENCLAW_HOME Override OpenClaw home directory (default: ~/.openclaw)",
|
|
121
|
+
help_env_openim: " OPENIM_RELAY_URL / OPENIM_RELAY_TOKEN",
|
|
122
|
+
help_env_relay_url: ` TESTNEXTIM_RELAY_URL Override relay base URL (default: ${DEFAULT_RELAY_URL})`,
|
|
123
|
+
help_env_relay_token: " TESTNEXTIM_RELAY_TOKEN Bearer token used for pair publish/bind endpoints",
|
|
124
|
+
help_env_gateway_base:
|
|
125
|
+
" OPENCLAW_TESTNEXTIM_GATEWAY_BASE_URL Local gateway base (overrides openclaw.json gateway.port)",
|
|
126
|
+
help_env_gateway_port:
|
|
127
|
+
" OPENCLAW_GATEWAY_PORT / OPENCLAW_GATEWAY_HOST Optional explicit local gateway host/port override",
|
|
128
|
+
config_read_failed: "Cannot read config file: {path}",
|
|
129
|
+
config_invalid_json: "Invalid JSON in config file: {path}",
|
|
130
|
+
fail_prefix: CLI_COMMAND_NAME,
|
|
131
|
+
pair_usage_missing: `Pair code is required. Usage: ${CLI_COMMAND_NAME} pair <1234|123456|XXXX-XXXX>`,
|
|
132
|
+
relay_url_required: "A relay URL is required.",
|
|
133
|
+
relay_url_missing_detail: "Relay is enabled but no URL is available.",
|
|
134
|
+
relay_url_hint: `Use the built-in default (${DEFAULT_RELAY_URL}) or pass --relay / TESTNEXTIM_RELAY_URL.`,
|
|
135
|
+
pair_code_not_found: "Pair code not found: {code}",
|
|
136
|
+
pair_code_generate_in_app: "Generate a fresh pair code from the mobile app first.",
|
|
137
|
+
pair_code_consumed: "This pair code has already been consumed: {code}",
|
|
138
|
+
pair_missing_client_user_id: "This pair code is missing a client user ID.",
|
|
139
|
+
pair_regenerate_latest: "Generate the latest pair code in the app and try again.",
|
|
140
|
+
bound_host_exists: "This host is already bound to a device.",
|
|
141
|
+
current_client_user_id: "Current clientUserId: {value}",
|
|
142
|
+
active_pair_code: "Active pair code: {value}",
|
|
143
|
+
reset_first: `Run \`${CLI_COMMAND_NAME} reset\` first, then retry pairing.`,
|
|
144
|
+
binding_cleared: "Cleared binding: {value}",
|
|
145
|
+
restart_failed_after_config: "OpenClaw restart failed after updating config.",
|
|
146
|
+
restart_manual_retry: "Run `openclaw daemon restart` manually and try again.",
|
|
147
|
+
gateway_not_ready: "Local OpenClaw gateway `/v1/responses` is not ready.",
|
|
148
|
+
gateway_checked: "Checked: {url}",
|
|
149
|
+
gateway_http_expected: "HTTP {status} (expected non-401/403/404)",
|
|
150
|
+
gateway_request_failed: "{error}",
|
|
151
|
+
gateway_ready_hint:
|
|
152
|
+
"Make sure OpenClaw daemon is running and the responses endpoint is enabled.",
|
|
153
|
+
pair_success: "Pairing is ready. Return to the app to finish confirmation.",
|
|
154
|
+
pair_worker_failed: "Pairing initialization failed because the relay bridge worker could not start.",
|
|
155
|
+
setup_updated: "Updated config: {path}",
|
|
156
|
+
setup_ready: "Config already prepared: {path}",
|
|
157
|
+
setup_state_file: "State file: {path}",
|
|
158
|
+
setup_transport: "Chat transport mode: {mode}",
|
|
159
|
+
setup_restarted: "OpenClaw restarted.",
|
|
160
|
+
setup_restart_failed: "OpenClaw restart failed. Run this manually:",
|
|
161
|
+
no_active_binding: "No active binding found on relay.",
|
|
162
|
+
relay_reset_done: "Relay binding reset: done",
|
|
163
|
+
relay_reset_empty: "Relay binding reset: nothing to clear",
|
|
164
|
+
relay_reset_skipped: "Relay binding reset: skipped",
|
|
165
|
+
stopped_bridge_count: "Stopped relay bridge processes: {count}",
|
|
166
|
+
local_state_reset: "Local state reset: {path}",
|
|
167
|
+
reset_ready: `You can now run \`${CLI_COMMAND_NAME} pair <code>\` again.`,
|
|
168
|
+
status_config: "Config: {value}",
|
|
169
|
+
status_channel: "Channel: {value}",
|
|
170
|
+
status_enabled: "Enabled: {value}",
|
|
171
|
+
status_bind_base: "Bind Base: {value}",
|
|
172
|
+
status_relay_url: "Relay URL: {value}",
|
|
173
|
+
status_transport: "Transport Mode: {value}",
|
|
174
|
+
status_gateway_base: "Local Gateway Base: {value}",
|
|
175
|
+
status_webhook_path: "Webhook Path: {value}",
|
|
176
|
+
status_bind_path: "Bind Path: {value}",
|
|
177
|
+
status_gateway_id: "Relay Gateway ID: {value}",
|
|
178
|
+
status_client_token: "Relay Client Token: {value}",
|
|
179
|
+
status_gateway_token: "Relay Gateway Token: {value}",
|
|
180
|
+
status_app_secret: "App Secret: {value}",
|
|
181
|
+
status_access_token: "Access Token: {value}",
|
|
182
|
+
status_linked_user: "Linked User: {value}",
|
|
183
|
+
yes: "yes",
|
|
184
|
+
no: "no",
|
|
185
|
+
set: "set",
|
|
186
|
+
missing: "missing",
|
|
187
|
+
not_set: "(not set)",
|
|
188
|
+
not_linked: "(not linked)",
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
function detectCliLanguage() {
|
|
193
|
+
const candidates = [
|
|
194
|
+
process.env.LC_ALL,
|
|
195
|
+
process.env.LC_MESSAGES,
|
|
196
|
+
process.env.LANG,
|
|
197
|
+
process.env.LANGUAGE,
|
|
198
|
+
process.env.VSLANG,
|
|
199
|
+
Intl.DateTimeFormat().resolvedOptions().locale,
|
|
200
|
+
];
|
|
201
|
+
for (const candidate of candidates) {
|
|
202
|
+
const normalized = String(candidate ?? "").trim().toLowerCase();
|
|
203
|
+
if (!normalized) {
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (normalized.startsWith("zh")) {
|
|
207
|
+
return "zh";
|
|
208
|
+
}
|
|
209
|
+
if (normalized.startsWith("en")) {
|
|
210
|
+
return "en";
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return "en";
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function t(key, args = {}) {
|
|
217
|
+
const table = CLI_I18N[CLI_LANGUAGE] || CLI_I18N.en;
|
|
218
|
+
const fallback = CLI_I18N.en[key] ?? key;
|
|
219
|
+
let message = table[key] ?? fallback;
|
|
220
|
+
for (const [name, value] of Object.entries(args)) {
|
|
221
|
+
message = message.replaceAll(`{${name}}`, String(value));
|
|
222
|
+
}
|
|
223
|
+
return message;
|
|
224
|
+
}
|
|
33
225
|
|
|
34
226
|
function printHelp() {
|
|
35
227
|
console.log(
|
|
36
228
|
[
|
|
37
|
-
|
|
229
|
+
t("help_title"),
|
|
38
230
|
"",
|
|
39
|
-
"
|
|
231
|
+
t("help_usage"),
|
|
40
232
|
` ${CLI_COMMAND_NAME} setup [--relay <url>] [--public-base <url>] [--mode <relay>] [--account <id>] [--restart|--no-restart] [--json]`,
|
|
41
233
|
` ${CLI_COMMAND_NAME} pair <1234|123456|XXXX-XXXX> [--mode <relay>]`,
|
|
42
234
|
` ${CLI_COMMAND_NAME} reset [--relay <url>] [--gateway <url>] [--json]`,
|
|
@@ -44,25 +236,25 @@ function printHelp() {
|
|
|
44
236
|
` ${CLI_COMMAND_NAME} pair-url [<1234|123456|XXXX-XXXX>] [--account <id>] [--code <1234|123456|XXXX-XXXX>] [--json]`,
|
|
45
237
|
` ${CLI_COMMAND_NAME} status [--json]`,
|
|
46
238
|
"",
|
|
47
|
-
|
|
239
|
+
t("help_package"),
|
|
48
240
|
"",
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
241
|
+
t("help_environment"),
|
|
242
|
+
t("help_env_home"),
|
|
243
|
+
t("help_env_openim"),
|
|
244
|
+
t("help_env_relay_url"),
|
|
245
|
+
t("help_env_relay_token"),
|
|
246
|
+
t("help_env_gateway_base"),
|
|
247
|
+
t("help_env_gateway_port"),
|
|
56
248
|
"",
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
249
|
+
t("help_tip"),
|
|
250
|
+
t("help_tip_pair"),
|
|
251
|
+
t("help_tip_no_serve"),
|
|
60
252
|
].join("\n"),
|
|
61
253
|
);
|
|
62
254
|
}
|
|
63
255
|
|
|
64
256
|
function fail(message, code = 1) {
|
|
65
|
-
console.error(`${
|
|
257
|
+
console.error(`${t("fail_prefix")}: ${message}`);
|
|
66
258
|
process.exit(code);
|
|
67
259
|
}
|
|
68
260
|
|
|
@@ -226,12 +418,12 @@ function readJsonFile(filePath) {
|
|
|
226
418
|
try {
|
|
227
419
|
content = fs.readFileSync(filePath, "utf8");
|
|
228
420
|
} catch {
|
|
229
|
-
fail(
|
|
421
|
+
fail(t("config_read_failed", { path: filePath }));
|
|
230
422
|
}
|
|
231
423
|
try {
|
|
232
424
|
return JSON.parse(content);
|
|
233
425
|
} catch {
|
|
234
|
-
fail(
|
|
426
|
+
fail(t("config_invalid_json", { path: filePath }));
|
|
235
427
|
}
|
|
236
428
|
}
|
|
237
429
|
|
|
@@ -2392,7 +2584,7 @@ async function runPair({
|
|
|
2392
2584
|
serveRelay,
|
|
2393
2585
|
}) {
|
|
2394
2586
|
if (!explicitCode || !String(explicitCode).trim()) {
|
|
2395
|
-
fail(
|
|
2587
|
+
fail(t("pair_usage_missing"));
|
|
2396
2588
|
}
|
|
2397
2589
|
const code = normalizeProvidedCode(explicitCode);
|
|
2398
2590
|
const configPath = resolveOpenClawConfigPath();
|
|
@@ -2402,9 +2594,9 @@ async function runPair({
|
|
|
2402
2594
|
if (!relayUrl) {
|
|
2403
2595
|
fail(
|
|
2404
2596
|
[
|
|
2405
|
-
"
|
|
2406
|
-
"
|
|
2407
|
-
|
|
2597
|
+
t("relay_url_required"),
|
|
2598
|
+
t("relay_url_missing_detail"),
|
|
2599
|
+
t("relay_url_hint"),
|
|
2408
2600
|
].join("\n"),
|
|
2409
2601
|
);
|
|
2410
2602
|
}
|
|
@@ -2413,13 +2605,13 @@ async function runPair({
|
|
|
2413
2605
|
if (!currentSession) {
|
|
2414
2606
|
fail(
|
|
2415
2607
|
[
|
|
2416
|
-
|
|
2417
|
-
"
|
|
2608
|
+
t("pair_code_not_found", { code }),
|
|
2609
|
+
t("pair_code_generate_in_app"),
|
|
2418
2610
|
].join("\n"),
|
|
2419
2611
|
);
|
|
2420
2612
|
}
|
|
2421
2613
|
if (currentSession.consumed) {
|
|
2422
|
-
fail(
|
|
2614
|
+
fail(t("pair_code_consumed", { code }));
|
|
2423
2615
|
}
|
|
2424
2616
|
|
|
2425
2617
|
const accountId = normalizeAccountId(currentSession.accountId || account);
|
|
@@ -2431,8 +2623,8 @@ async function runPair({
|
|
|
2431
2623
|
if (!clientUserId) {
|
|
2432
2624
|
fail(
|
|
2433
2625
|
[
|
|
2434
|
-
|
|
2435
|
-
"
|
|
2626
|
+
t("pair_missing_client_user_id"),
|
|
2627
|
+
t("pair_regenerate_latest"),
|
|
2436
2628
|
].join("\n"),
|
|
2437
2629
|
);
|
|
2438
2630
|
}
|
|
@@ -2445,9 +2637,6 @@ async function runPair({
|
|
|
2445
2637
|
writeJsonFile(configPath, config);
|
|
2446
2638
|
}
|
|
2447
2639
|
section = readChannelSection(config);
|
|
2448
|
-
if (!json && prepared.changed) {
|
|
2449
|
-
console.log("Updated openclaw.json: removed stale testnextim plugin/channel config.");
|
|
2450
|
-
}
|
|
2451
2640
|
|
|
2452
2641
|
const bindPath = normalizePath(section.bindPath, DEFAULT_BIND_PATH);
|
|
2453
2642
|
|
|
@@ -2499,12 +2688,14 @@ async function runPair({
|
|
|
2499
2688
|
if (existingBinding && existingCode !== code) {
|
|
2500
2689
|
fail(
|
|
2501
2690
|
[
|
|
2502
|
-
"
|
|
2691
|
+
t("bound_host_exists"),
|
|
2503
2692
|
existingBinding.clientUserId
|
|
2504
|
-
?
|
|
2693
|
+
? t("current_client_user_id", { value: existingBinding.clientUserId })
|
|
2694
|
+
: null,
|
|
2695
|
+
existingBinding.code
|
|
2696
|
+
? t("active_pair_code", { value: existingBinding.code })
|
|
2505
2697
|
: null,
|
|
2506
|
-
|
|
2507
|
-
`Run \`${CLI_COMMAND_NAME} reset\` first to clear the current binding, then retry pairing.`,
|
|
2698
|
+
t("reset_first"),
|
|
2508
2699
|
]
|
|
2509
2700
|
.filter(Boolean)
|
|
2510
2701
|
.join("\n"),
|
|
@@ -2530,8 +2721,8 @@ async function runPair({
|
|
|
2530
2721
|
if (!restartResult.ok) {
|
|
2531
2722
|
fail(
|
|
2532
2723
|
[
|
|
2533
|
-
"
|
|
2534
|
-
"
|
|
2724
|
+
t("restart_failed_after_config"),
|
|
2725
|
+
t("restart_manual_retry"),
|
|
2535
2726
|
restartResult.stderr?.trim() || restartResult.stdout?.trim() || "",
|
|
2536
2727
|
]
|
|
2537
2728
|
.filter(Boolean)
|
|
@@ -2551,8 +2742,8 @@ async function runPair({
|
|
|
2551
2742
|
if (!restartResult.ok) {
|
|
2552
2743
|
fail(
|
|
2553
2744
|
[
|
|
2554
|
-
"
|
|
2555
|
-
"
|
|
2745
|
+
t("restart_failed_after_config"),
|
|
2746
|
+
t("restart_manual_retry"),
|
|
2556
2747
|
restartResult.stderr?.trim() || restartResult.stdout?.trim() || "",
|
|
2557
2748
|
]
|
|
2558
2749
|
.filter(Boolean)
|
|
@@ -2569,12 +2760,12 @@ async function runPair({
|
|
|
2569
2760
|
if (!gatewayProbe.ok) {
|
|
2570
2761
|
fail(
|
|
2571
2762
|
[
|
|
2572
|
-
"
|
|
2573
|
-
|
|
2763
|
+
t("gateway_not_ready"),
|
|
2764
|
+
t("gateway_checked", { url: gatewayProbe.url }),
|
|
2574
2765
|
gatewayProbe.status
|
|
2575
|
-
?
|
|
2576
|
-
: gatewayProbe.error || "request failed",
|
|
2577
|
-
"
|
|
2766
|
+
? t("gateway_http_expected", { status: gatewayProbe.status })
|
|
2767
|
+
: t("gateway_request_failed", { error: gatewayProbe.error || "request failed" }),
|
|
2768
|
+
t("gateway_ready_hint"),
|
|
2578
2769
|
].join("\n"),
|
|
2579
2770
|
);
|
|
2580
2771
|
}
|
|
@@ -2635,31 +2826,15 @@ async function runPair({
|
|
|
2635
2826
|
if (json) {
|
|
2636
2827
|
console.log(JSON.stringify(output, null, 2));
|
|
2637
2828
|
} else {
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
console.log(`Relay Lookup: ${relayResult.relayLookupUrl}`);
|
|
2646
|
-
}
|
|
2647
|
-
if (relayCredentials?.gatewayId) {
|
|
2648
|
-
console.log(`Relay Gateway ID: ${relayCredentials.gatewayId}`);
|
|
2649
|
-
}
|
|
2650
|
-
if (clientUserId) {
|
|
2651
|
-
console.log(`Client User ID: ${clientUserId}`);
|
|
2652
|
-
}
|
|
2653
|
-
if (serveRelay) {
|
|
2654
|
-
if (output.relayWorkerResult?.started) {
|
|
2655
|
-
console.log("Relay bridge worker: started (detached)");
|
|
2656
|
-
} else if (output.relayWorkerResult?.alreadyRunning) {
|
|
2657
|
-
console.log(`Relay bridge worker: already running (${output.relayWorkerResult.mode})`);
|
|
2658
|
-
} else {
|
|
2659
|
-
console.log("Relay bridge worker: failed to start");
|
|
2660
|
-
}
|
|
2829
|
+
if (
|
|
2830
|
+
serveRelay &&
|
|
2831
|
+
output.relayWorkerResult &&
|
|
2832
|
+
!output.relayWorkerResult.started &&
|
|
2833
|
+
!output.relayWorkerResult.alreadyRunning
|
|
2834
|
+
) {
|
|
2835
|
+
fail(t("pair_worker_failed"));
|
|
2661
2836
|
}
|
|
2662
|
-
console.log(
|
|
2837
|
+
console.log(t("pair_success"));
|
|
2663
2838
|
}
|
|
2664
2839
|
}
|
|
2665
2840
|
|
|
@@ -2718,26 +2893,28 @@ async function runReset({ json, relay, noRelay, gateway }) {
|
|
|
2718
2893
|
}
|
|
2719
2894
|
|
|
2720
2895
|
if (activeBinding) {
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2896
|
+
const bindingLabel = [
|
|
2897
|
+
activeBinding.clientUserId || "(unknown client)",
|
|
2898
|
+
activeBinding.code ? `code ${activeBinding.code}` : null,
|
|
2899
|
+
]
|
|
2900
|
+
.filter(Boolean)
|
|
2901
|
+
.join(" · ");
|
|
2902
|
+
console.log(t("binding_cleared", { value: bindingLabel }));
|
|
2726
2903
|
} else {
|
|
2727
|
-
console.log("
|
|
2904
|
+
console.log(t("no_active_binding"));
|
|
2728
2905
|
}
|
|
2729
2906
|
if (relayResetResult?.ok) {
|
|
2730
|
-
console.log("
|
|
2907
|
+
console.log(t("relay_reset_done"));
|
|
2731
2908
|
} else if (relayResetResult?.notFound) {
|
|
2732
|
-
console.log("
|
|
2909
|
+
console.log(t("relay_reset_empty"));
|
|
2733
2910
|
} else {
|
|
2734
|
-
console.log("
|
|
2911
|
+
console.log(t("relay_reset_skipped"));
|
|
2735
2912
|
}
|
|
2736
2913
|
if (stoppedBridges.count > 0) {
|
|
2737
|
-
console.log(
|
|
2914
|
+
console.log(t("stopped_bridge_count", { count: stoppedBridges.count }));
|
|
2738
2915
|
}
|
|
2739
|
-
console.log(
|
|
2740
|
-
console.log(
|
|
2916
|
+
console.log(t("local_state_reset", { path: nextState.statePath }));
|
|
2917
|
+
console.log(t("reset_ready"));
|
|
2741
2918
|
}
|
|
2742
2919
|
|
|
2743
2920
|
function runSetup({
|
|
@@ -2755,9 +2932,9 @@ function runSetup({
|
|
|
2755
2932
|
if (!relayUrl) {
|
|
2756
2933
|
fail(
|
|
2757
2934
|
[
|
|
2758
|
-
"
|
|
2759
|
-
"
|
|
2760
|
-
|
|
2935
|
+
t("relay_url_required"),
|
|
2936
|
+
t("relay_url_missing_detail"),
|
|
2937
|
+
t("relay_url_hint"),
|
|
2761
2938
|
].join("\n"),
|
|
2762
2939
|
);
|
|
2763
2940
|
}
|
|
@@ -2823,20 +3000,24 @@ function runSetup({
|
|
|
2823
3000
|
}
|
|
2824
3001
|
|
|
2825
3002
|
if (setupChanges.length > 0) {
|
|
2826
|
-
console.log(
|
|
3003
|
+
console.log(t("setup_updated", { path: configPath }));
|
|
2827
3004
|
for (const item of setupChanges) {
|
|
2828
3005
|
console.log(`- ${item}`);
|
|
2829
3006
|
}
|
|
2830
3007
|
} else {
|
|
2831
|
-
console.log(
|
|
3008
|
+
console.log(t("setup_ready", { path: configPath }));
|
|
2832
3009
|
}
|
|
2833
|
-
console.log(
|
|
2834
|
-
console.log(
|
|
3010
|
+
console.log(t("setup_state_file", { path: persistedSettings.statePath }));
|
|
3011
|
+
console.log(
|
|
3012
|
+
t("setup_transport", {
|
|
3013
|
+
mode: normalizeChatTransportMode(section.chatTransportMode, "relay"),
|
|
3014
|
+
}),
|
|
3015
|
+
);
|
|
2835
3016
|
if (restart) {
|
|
2836
3017
|
if (restartResult?.ok) {
|
|
2837
|
-
console.log("
|
|
3018
|
+
console.log(t("setup_restarted"));
|
|
2838
3019
|
} else {
|
|
2839
|
-
console.log("
|
|
3020
|
+
console.log(t("setup_restart_failed"));
|
|
2840
3021
|
console.log(" openclaw daemon restart");
|
|
2841
3022
|
if (restartResult?.stderr?.trim()) {
|
|
2842
3023
|
console.log(restartResult.stderr.trim());
|
|
@@ -3043,21 +3224,37 @@ function runStatus({ json }) {
|
|
|
3043
3224
|
return;
|
|
3044
3225
|
}
|
|
3045
3226
|
|
|
3046
|
-
console.log(
|
|
3047
|
-
console.log(
|
|
3048
|
-
console.log(
|
|
3049
|
-
console.log(
|
|
3050
|
-
console.log(
|
|
3051
|
-
console.log(
|
|
3052
|
-
console.log(
|
|
3053
|
-
console.log(
|
|
3054
|
-
console.log(
|
|
3055
|
-
console.log(
|
|
3056
|
-
console.log(
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3227
|
+
console.log(t("status_config", { value: status.configPath }));
|
|
3228
|
+
console.log(t("status_channel", { value: status.channel }));
|
|
3229
|
+
console.log(t("status_enabled", { value: status.enabled ? t("yes") : t("no") }));
|
|
3230
|
+
console.log(t("status_bind_base", { value: status.bindPublicBaseUrl ?? t("not_set") }));
|
|
3231
|
+
console.log(t("status_relay_url", { value: status.relayUrl ?? t("not_set") }));
|
|
3232
|
+
console.log(t("status_transport", { value: status.transportMode }));
|
|
3233
|
+
console.log(t("status_gateway_base", { value: status.gatewayBaseUrl }));
|
|
3234
|
+
console.log(t("status_webhook_path", { value: status.webhookPath }));
|
|
3235
|
+
console.log(t("status_bind_path", { value: status.bindPath }));
|
|
3236
|
+
console.log(t("status_gateway_id", { value: status.relayGatewayId ?? t("missing") }));
|
|
3237
|
+
console.log(
|
|
3238
|
+
t("status_client_token", {
|
|
3239
|
+
value: status.hasRelayClientToken ? t("set") : t("missing"),
|
|
3240
|
+
}),
|
|
3241
|
+
);
|
|
3242
|
+
console.log(
|
|
3243
|
+
t("status_gateway_token", {
|
|
3244
|
+
value: status.hasRelayGatewayToken ? t("set") : t("missing"),
|
|
3245
|
+
}),
|
|
3246
|
+
);
|
|
3247
|
+
console.log(
|
|
3248
|
+
t("status_app_secret", {
|
|
3249
|
+
value: status.hasAppSecret ? t("set") : t("missing"),
|
|
3250
|
+
}),
|
|
3251
|
+
);
|
|
3252
|
+
console.log(
|
|
3253
|
+
t("status_access_token", {
|
|
3254
|
+
value: status.hasAccessToken ? t("set") : t("missing"),
|
|
3255
|
+
}),
|
|
3256
|
+
);
|
|
3257
|
+
console.log(t("status_linked_user", { value: status.linkedUserId ?? t("not_linked") }));
|
|
3061
3258
|
}
|
|
3062
3259
|
|
|
3063
3260
|
async function main() {
|