nextclaw 0.13.8 → 0.13.10
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/dist/cli/index.js +574 -90
- package/package.json +6 -6
- package/ui-dist/assets/ChannelsList-DH1Ur9XW.js +0 -1
- package/ui-dist/assets/ChatPage-YTDcN7XS.js +0 -38
- package/ui-dist/assets/DocBrowser-Bi-RpLIw.js +0 -1
- package/ui-dist/assets/LogoBadge-BCR9CU7n.js +0 -1
- package/ui-dist/assets/MarketplacePage-BgCdiku7.js +0 -49
- package/ui-dist/assets/McpMarketplacePage-nyCbiQH6.js +0 -40
- package/ui-dist/assets/ModelConfig-Cf4AAYaB.js +0 -1
- package/ui-dist/assets/ProvidersList-CfkfKQbw.js +0 -1
- package/ui-dist/assets/RuntimeConfig-BI-zClCl.js +0 -1
- package/ui-dist/assets/SearchConfig-MBmvco1J.js +0 -1
- package/ui-dist/assets/SecretsConfig-CC2B6pVQ.js +0 -3
- package/ui-dist/assets/SessionsConfig-CTxJeVQs.js +0 -2
- package/ui-dist/assets/chat-message-5OiyZViy.js +0 -3
- package/ui-dist/assets/config-hints-CApS3K_7.js +0 -1
- package/ui-dist/assets/config-layout-BHnOoweL.js +0 -1
- package/ui-dist/assets/index-C2OKcVdN.css +0 -1
- package/ui-dist/assets/index-ElnZdv5o.js +0 -1
- package/ui-dist/assets/index-LgjZxLjc.js +0 -8
- package/ui-dist/assets/label-CPdcDrir.js +0 -1
- package/ui-dist/assets/marketplace-localization-Dk31LJJJ.js +0 -1
- package/ui-dist/assets/page-layout-B8V5_vM_.js +0 -1
- package/ui-dist/assets/popover-Bk53A74_.js +0 -1
- package/ui-dist/assets/provider-models-D3B_xWXx.js +0 -1
- package/ui-dist/assets/security-config-BNjgoyo4.js +0 -1
- package/ui-dist/assets/skeleton-NPxxR-L0.js +0 -1
- package/ui-dist/assets/switch-EowdzMK2.js +0 -1
- package/ui-dist/assets/tabs-custom-BjLv-uCT.js +0 -1
- package/ui-dist/assets/useConfirmDialog-TJcJQMfu.js +0 -5
- package/ui-dist/assets/vendor-425xp8cv.js +0 -407
- package/ui-dist/index.html +0 -18
package/dist/cli/index.js
CHANGED
|
@@ -7,9 +7,9 @@ import { registerRemoteCommands } from "@nextclaw/remote";
|
|
|
7
7
|
|
|
8
8
|
// src/cli/runtime.ts
|
|
9
9
|
import {
|
|
10
|
-
loadConfig as
|
|
10
|
+
loadConfig as loadConfig15,
|
|
11
11
|
saveConfig as saveConfig10,
|
|
12
|
-
getConfigPath as
|
|
12
|
+
getConfigPath as getConfigPath8,
|
|
13
13
|
getDataDir as getDataDir9,
|
|
14
14
|
ConfigSchema as ConfigSchema2,
|
|
15
15
|
getWorkspacePath as getWorkspacePath10,
|
|
@@ -32,7 +32,7 @@ import { existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as re
|
|
|
32
32
|
import { join as join8, resolve as resolve12 } from "path";
|
|
33
33
|
import { createInterface as createInterface3 } from "readline";
|
|
34
34
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
35
|
-
import { spawn as
|
|
35
|
+
import { spawn as spawn4 } from "child_process";
|
|
36
36
|
|
|
37
37
|
// src/cli/restart-coordinator.ts
|
|
38
38
|
var RestartCoordinator = class {
|
|
@@ -3001,8 +3001,75 @@ function readLoginPayload(raw) {
|
|
|
3001
3001
|
}
|
|
3002
3002
|
return { token, role };
|
|
3003
3003
|
}
|
|
3004
|
+
function persistPlatformToken(params) {
|
|
3005
|
+
params.nextclawProvider.apiBase = params.v1Base;
|
|
3006
|
+
params.nextclawProvider.apiKey = params.token;
|
|
3007
|
+
params.providers.nextclaw = params.nextclawProvider;
|
|
3008
|
+
saveConfig6(params.config, params.configPath);
|
|
3009
|
+
}
|
|
3010
|
+
function parseJsonText(raw) {
|
|
3011
|
+
try {
|
|
3012
|
+
return JSON.parse(raw);
|
|
3013
|
+
} catch {
|
|
3014
|
+
return null;
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
function readPlatformErrorMessage(raw, fallbackStatus) {
|
|
3018
|
+
const parsed = parseJsonText(raw);
|
|
3019
|
+
return typeof parsed === "object" && parsed && "error" in parsed && typeof parsed.error?.message === "string" ? parsed.error.message : raw || `Request failed (${fallbackStatus})`;
|
|
3020
|
+
}
|
|
3021
|
+
function readBrowserAuthStartPayload(raw) {
|
|
3022
|
+
const parsed = parseJsonText(raw);
|
|
3023
|
+
const data = typeof parsed === "object" && parsed && "data" in parsed ? parsed.data : null;
|
|
3024
|
+
const sessionId = typeof data?.sessionId === "string" ? data.sessionId.trim() : "";
|
|
3025
|
+
const verificationUri = typeof data?.verificationUri === "string" ? data.verificationUri.trim() : "";
|
|
3026
|
+
const expiresAt = typeof data?.expiresAt === "string" ? data.expiresAt.trim() : "";
|
|
3027
|
+
const intervalMs = typeof data?.intervalMs === "number" && Number.isFinite(data.intervalMs) ? Math.max(1e3, Math.trunc(data.intervalMs)) : 1500;
|
|
3028
|
+
if (!sessionId || !verificationUri || !expiresAt) {
|
|
3029
|
+
throw new Error("Browser authorization session payload is incomplete.");
|
|
3030
|
+
}
|
|
3031
|
+
return {
|
|
3032
|
+
sessionId,
|
|
3033
|
+
verificationUri,
|
|
3034
|
+
expiresAt,
|
|
3035
|
+
intervalMs
|
|
3036
|
+
};
|
|
3037
|
+
}
|
|
3038
|
+
function readBrowserAuthPollPayload(raw) {
|
|
3039
|
+
const parsed = parseJsonText(raw);
|
|
3040
|
+
const data = typeof parsed === "object" && parsed && "data" in parsed ? parsed.data : null;
|
|
3041
|
+
const status = typeof data?.status === "string" ? data.status.trim() : "";
|
|
3042
|
+
if (status === "pending") {
|
|
3043
|
+
return {
|
|
3044
|
+
status,
|
|
3045
|
+
nextPollMs: typeof data?.nextPollMs === "number" && Number.isFinite(data.nextPollMs) ? Math.max(1e3, Math.trunc(data.nextPollMs)) : 1500
|
|
3046
|
+
};
|
|
3047
|
+
}
|
|
3048
|
+
if (status === "expired") {
|
|
3049
|
+
return {
|
|
3050
|
+
status,
|
|
3051
|
+
message: typeof data?.message === "string" && data.message.trim() ? data.message.trim() : "Authorization session expired."
|
|
3052
|
+
};
|
|
3053
|
+
}
|
|
3054
|
+
if (status !== "authorized") {
|
|
3055
|
+
throw new Error("Unexpected browser authorization status.");
|
|
3056
|
+
}
|
|
3057
|
+
const token = typeof data?.token === "string" ? data.token.trim() : "";
|
|
3058
|
+
const user = typeof data?.user === "object" && data.user ? data.user : null;
|
|
3059
|
+
const role = typeof user?.role === "string" ? user.role.trim() : "user";
|
|
3060
|
+
const email = typeof user?.email === "string" ? user.email.trim() : "";
|
|
3061
|
+
if (!token || !email) {
|
|
3062
|
+
throw new Error("Authorized browser login payload is incomplete.");
|
|
3063
|
+
}
|
|
3064
|
+
return {
|
|
3065
|
+
status,
|
|
3066
|
+
token,
|
|
3067
|
+
role,
|
|
3068
|
+
email
|
|
3069
|
+
};
|
|
3070
|
+
}
|
|
3004
3071
|
var PlatformAuthCommands = class {
|
|
3005
|
-
async
|
|
3072
|
+
async loginResult(opts = {}) {
|
|
3006
3073
|
const { configPath, config: config2, providers, nextclawProvider, platformBase, v1Base, inputApiBase } = resolveProviderConfig(opts);
|
|
3007
3074
|
const { email, password } = await resolveCredentials(opts);
|
|
3008
3075
|
const endpoint = opts.register ? `${platformBase}/platform/auth/register` : `${platformBase}/platform/auth/login`;
|
|
@@ -3015,23 +3082,105 @@ var PlatformAuthCommands = class {
|
|
|
3015
3082
|
});
|
|
3016
3083
|
const raw = await response.text();
|
|
3017
3084
|
if (!response.ok) {
|
|
3018
|
-
|
|
3019
|
-
try {
|
|
3020
|
-
parsed = JSON.parse(raw);
|
|
3021
|
-
} catch {
|
|
3022
|
-
parsed = null;
|
|
3023
|
-
}
|
|
3024
|
-
const maybeMessage = typeof parsed === "object" && parsed && "error" in parsed && typeof parsed.error?.message === "string" ? parsed.error.message : raw || `Request failed (${response.status})`;
|
|
3025
|
-
throw new Error(buildPlatformApiBaseErrorMessage(inputApiBase, maybeMessage));
|
|
3085
|
+
throw new Error(buildPlatformApiBaseErrorMessage(inputApiBase, readPlatformErrorMessage(raw, response.status)));
|
|
3026
3086
|
}
|
|
3027
3087
|
const { token, role } = readLoginPayload(raw);
|
|
3028
|
-
|
|
3029
|
-
|
|
3088
|
+
persistPlatformToken({
|
|
3089
|
+
configPath,
|
|
3090
|
+
config: config2,
|
|
3091
|
+
providers,
|
|
3092
|
+
nextclawProvider,
|
|
3093
|
+
v1Base,
|
|
3094
|
+
token
|
|
3095
|
+
});
|
|
3096
|
+
return {
|
|
3097
|
+
token,
|
|
3098
|
+
role,
|
|
3099
|
+
email,
|
|
3100
|
+
platformBase,
|
|
3101
|
+
v1Base
|
|
3102
|
+
};
|
|
3103
|
+
}
|
|
3104
|
+
async startBrowserAuth(opts = {}) {
|
|
3105
|
+
const { platformBase, v1Base, inputApiBase } = resolveProviderConfig(opts);
|
|
3106
|
+
const response = await fetch(`${platformBase}/platform/auth/browser/start`, {
|
|
3107
|
+
method: "POST",
|
|
3108
|
+
headers: {
|
|
3109
|
+
"Content-Type": "application/json"
|
|
3110
|
+
},
|
|
3111
|
+
body: JSON.stringify({})
|
|
3112
|
+
});
|
|
3113
|
+
const raw = await response.text();
|
|
3114
|
+
if (!response.ok) {
|
|
3115
|
+
throw new Error(buildPlatformApiBaseErrorMessage(inputApiBase, readPlatformErrorMessage(raw, response.status)));
|
|
3116
|
+
}
|
|
3117
|
+
const result = readBrowserAuthStartPayload(raw);
|
|
3118
|
+
return {
|
|
3119
|
+
...result,
|
|
3120
|
+
platformBase,
|
|
3121
|
+
v1Base
|
|
3122
|
+
};
|
|
3123
|
+
}
|
|
3124
|
+
async pollBrowserAuth(params) {
|
|
3125
|
+
const { configPath, config: config2, providers, nextclawProvider, platformBase, v1Base, inputApiBase } = resolveProviderConfig({
|
|
3126
|
+
apiBase: params.apiBase
|
|
3127
|
+
});
|
|
3128
|
+
const response = await fetch(`${platformBase}/platform/auth/browser/poll`, {
|
|
3129
|
+
method: "POST",
|
|
3130
|
+
headers: {
|
|
3131
|
+
"Content-Type": "application/json"
|
|
3132
|
+
},
|
|
3133
|
+
body: JSON.stringify({
|
|
3134
|
+
sessionId: params.sessionId
|
|
3135
|
+
})
|
|
3136
|
+
});
|
|
3137
|
+
const raw = await response.text();
|
|
3138
|
+
if (!response.ok) {
|
|
3139
|
+
throw new Error(buildPlatformApiBaseErrorMessage(inputApiBase, readPlatformErrorMessage(raw, response.status)));
|
|
3140
|
+
}
|
|
3141
|
+
const result = readBrowserAuthPollPayload(raw);
|
|
3142
|
+
if (result.status === "pending") {
|
|
3143
|
+
return {
|
|
3144
|
+
status: "pending",
|
|
3145
|
+
nextPollMs: result.nextPollMs ?? 1500
|
|
3146
|
+
};
|
|
3147
|
+
}
|
|
3148
|
+
if (result.status === "expired") {
|
|
3149
|
+
return {
|
|
3150
|
+
status: "expired",
|
|
3151
|
+
message: result.message ?? "Authorization session expired."
|
|
3152
|
+
};
|
|
3153
|
+
}
|
|
3154
|
+
persistPlatformToken({
|
|
3155
|
+
configPath,
|
|
3156
|
+
config: config2,
|
|
3157
|
+
providers,
|
|
3158
|
+
nextclawProvider,
|
|
3159
|
+
v1Base,
|
|
3160
|
+
token: result.token ?? ""
|
|
3161
|
+
});
|
|
3162
|
+
return {
|
|
3163
|
+
status: "authorized",
|
|
3164
|
+
token: result.token ?? "",
|
|
3165
|
+
role: result.role ?? "user",
|
|
3166
|
+
email: result.email ?? "",
|
|
3167
|
+
platformBase,
|
|
3168
|
+
v1Base
|
|
3169
|
+
};
|
|
3170
|
+
}
|
|
3171
|
+
async login(opts = {}) {
|
|
3172
|
+
const result = await this.loginResult(opts);
|
|
3173
|
+
console.log(`\u2713 Logged in to NextClaw platform (${result.platformBase})`);
|
|
3174
|
+
console.log(`\u2713 Account: ${result.email} (${result.role})`);
|
|
3175
|
+
console.log(`\u2713 Token saved into providers.nextclaw.apiKey`);
|
|
3176
|
+
}
|
|
3177
|
+
logout() {
|
|
3178
|
+
const { configPath, config: config2, providers, nextclawProvider } = resolveProviderConfig({});
|
|
3179
|
+
const cleared = Boolean(nextclawProvider.apiKey?.trim());
|
|
3180
|
+
nextclawProvider.apiKey = "";
|
|
3030
3181
|
providers.nextclaw = nextclawProvider;
|
|
3031
3182
|
saveConfig6(config2, configPath);
|
|
3032
|
-
|
|
3033
|
-
console.log(`\u2713 Account: ${email} (${role})`);
|
|
3034
|
-
console.log(`\u2713 Token saved into providers.nextclaw.apiKey`);
|
|
3183
|
+
return { cleared };
|
|
3035
3184
|
}
|
|
3036
3185
|
};
|
|
3037
3186
|
|
|
@@ -3112,6 +3261,9 @@ function normalizeOptionalString3(value) {
|
|
|
3112
3261
|
const trimmed = value.trim();
|
|
3113
3262
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
3114
3263
|
}
|
|
3264
|
+
function isPlatformSessionToken(value) {
|
|
3265
|
+
return typeof value === "string" && value.startsWith("nca.");
|
|
3266
|
+
}
|
|
3115
3267
|
function resolveConfiguredLocalOrigin(config2) {
|
|
3116
3268
|
const state = readServiceState();
|
|
3117
3269
|
if (state && isProcessRunning(state.pid) && Number.isFinite(state.uiPort)) {
|
|
@@ -3135,15 +3287,18 @@ async function probeLocalUi(localOrigin) {
|
|
|
3135
3287
|
}
|
|
3136
3288
|
}
|
|
3137
3289
|
var RemoteCommands = class {
|
|
3138
|
-
|
|
3290
|
+
updateConfig(params = {}) {
|
|
3139
3291
|
const config2 = loadConfig9(getConfigPath4());
|
|
3292
|
+
const nextEnabled = typeof params.enabled === "boolean" ? params.enabled : config2.remote.enabled;
|
|
3293
|
+
const nextPlatformApiBase = typeof params.apiBase === "string" ? params.apiBase.trim() : config2.remote.platformApiBase;
|
|
3294
|
+
const nextDeviceName = typeof params.name === "string" ? params.name.trim() : config2.remote.deviceName;
|
|
3140
3295
|
const next = {
|
|
3141
3296
|
...config2,
|
|
3142
3297
|
remote: {
|
|
3143
3298
|
...config2.remote,
|
|
3144
|
-
enabled:
|
|
3145
|
-
|
|
3146
|
-
|
|
3299
|
+
enabled: nextEnabled,
|
|
3300
|
+
platformApiBase: nextPlatformApiBase,
|
|
3301
|
+
deviceName: nextDeviceName
|
|
3147
3302
|
}
|
|
3148
3303
|
};
|
|
3149
3304
|
saveConfig7(next);
|
|
@@ -3152,20 +3307,15 @@ var RemoteCommands = class {
|
|
|
3152
3307
|
config: next
|
|
3153
3308
|
};
|
|
3154
3309
|
}
|
|
3310
|
+
enableConfig(opts = {}) {
|
|
3311
|
+
return this.updateConfig({
|
|
3312
|
+
enabled: true,
|
|
3313
|
+
apiBase: typeof opts.apiBase === "string" ? opts.apiBase : void 0,
|
|
3314
|
+
name: typeof opts.name === "string" ? opts.name : void 0
|
|
3315
|
+
});
|
|
3316
|
+
}
|
|
3155
3317
|
disableConfig() {
|
|
3156
|
-
|
|
3157
|
-
const next = {
|
|
3158
|
-
...config2,
|
|
3159
|
-
remote: {
|
|
3160
|
-
...config2.remote,
|
|
3161
|
-
enabled: false
|
|
3162
|
-
}
|
|
3163
|
-
};
|
|
3164
|
-
saveConfig7(next);
|
|
3165
|
-
return {
|
|
3166
|
-
changed: config2.remote.enabled !== next.remote.enabled,
|
|
3167
|
-
config: next
|
|
3168
|
-
};
|
|
3318
|
+
return this.updateConfig({ enabled: false });
|
|
3169
3319
|
}
|
|
3170
3320
|
async connect(opts = {}) {
|
|
3171
3321
|
const connector = createNextclawRemoteConnector();
|
|
@@ -3174,23 +3324,31 @@ var RemoteCommands = class {
|
|
|
3174
3324
|
mode: "foreground"
|
|
3175
3325
|
});
|
|
3176
3326
|
}
|
|
3177
|
-
|
|
3327
|
+
getStatusView() {
|
|
3178
3328
|
const config2 = loadConfig9(getConfigPath4());
|
|
3179
3329
|
const snapshot = resolveNextclawRemoteStatusSnapshot(config2);
|
|
3330
|
+
return {
|
|
3331
|
+
configuredEnabled: snapshot.configuredEnabled,
|
|
3332
|
+
runtime: snapshot.runtime,
|
|
3333
|
+
localOrigin: resolveConfiguredLocalOrigin(config2),
|
|
3334
|
+
deviceName: snapshot.runtime?.deviceName ?? normalizeOptionalString3(config2.remote.deviceName) ?? hostname(),
|
|
3335
|
+
platformBase: snapshot.runtime?.platformBase ?? normalizeOptionalString3(config2.remote.platformApiBase) ?? normalizeOptionalString3(config2.providers.nextclaw?.apiBase) ?? null
|
|
3336
|
+
};
|
|
3337
|
+
}
|
|
3338
|
+
async status(opts = {}) {
|
|
3339
|
+
const view = this.getStatusView();
|
|
3180
3340
|
if (opts.json) {
|
|
3181
|
-
console.log(JSON.stringify(
|
|
3341
|
+
console.log(JSON.stringify(view, null, 2));
|
|
3182
3342
|
return;
|
|
3183
3343
|
}
|
|
3184
|
-
const runtime2 =
|
|
3344
|
+
const runtime2 = view.runtime;
|
|
3185
3345
|
console.log("NextClaw Remote Status");
|
|
3186
|
-
console.log(`Enabled: ${
|
|
3346
|
+
console.log(`Enabled: ${view.configuredEnabled ? "yes" : "no"}`);
|
|
3187
3347
|
console.log(`Mode: ${runtime2?.mode ?? "service"}`);
|
|
3188
3348
|
console.log(`State: ${runtime2?.state ?? "disabled"}`);
|
|
3189
|
-
console.log(`Device: ${
|
|
3190
|
-
console.log(
|
|
3191
|
-
|
|
3192
|
-
);
|
|
3193
|
-
console.log(`Local origin: ${runtime2?.localOrigin ?? resolveConfiguredLocalOrigin(config2)}`);
|
|
3349
|
+
console.log(`Device: ${view.deviceName}`);
|
|
3350
|
+
console.log(`Platform: ${view.platformBase ?? "not set"}`);
|
|
3351
|
+
console.log(`Local origin: ${runtime2?.localOrigin ?? view.localOrigin}`);
|
|
3194
3352
|
if (runtime2?.deviceId) {
|
|
3195
3353
|
console.log(`Device ID: ${runtime2.deviceId}`);
|
|
3196
3354
|
}
|
|
@@ -3201,7 +3359,7 @@ var RemoteCommands = class {
|
|
|
3201
3359
|
console.log(`Last error: ${runtime2.lastError}`);
|
|
3202
3360
|
}
|
|
3203
3361
|
}
|
|
3204
|
-
async
|
|
3362
|
+
async getDoctorView() {
|
|
3205
3363
|
const config2 = loadConfig9(getConfigPath4());
|
|
3206
3364
|
const snapshot = resolveNextclawRemoteStatusSnapshot(config2);
|
|
3207
3365
|
const localOrigin = resolveConfiguredLocalOrigin(config2);
|
|
@@ -3216,8 +3374,8 @@ var RemoteCommands = class {
|
|
|
3216
3374
|
},
|
|
3217
3375
|
{
|
|
3218
3376
|
name: "platform-token",
|
|
3219
|
-
ok:
|
|
3220
|
-
detail: token ? "token configured" : 'run "nextclaw login" first'
|
|
3377
|
+
ok: isPlatformSessionToken(token),
|
|
3378
|
+
detail: isPlatformSessionToken(token) ? "platform session token configured" : 'run remote browser login or "nextclaw login" first'
|
|
3221
3379
|
},
|
|
3222
3380
|
{
|
|
3223
3381
|
name: "platform-api-base",
|
|
@@ -3235,12 +3393,20 @@ var RemoteCommands = class {
|
|
|
3235
3393
|
detail: snapshot.runtime ? snapshot.runtime.state : "no managed remote runtime detected"
|
|
3236
3394
|
}
|
|
3237
3395
|
];
|
|
3396
|
+
return {
|
|
3397
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3398
|
+
checks,
|
|
3399
|
+
snapshot
|
|
3400
|
+
};
|
|
3401
|
+
}
|
|
3402
|
+
async doctor(opts = {}) {
|
|
3403
|
+
const report = await this.getDoctorView();
|
|
3238
3404
|
if (opts.json) {
|
|
3239
|
-
console.log(JSON.stringify(
|
|
3405
|
+
console.log(JSON.stringify(report, null, 2));
|
|
3240
3406
|
return;
|
|
3241
3407
|
}
|
|
3242
3408
|
console.log("NextClaw Remote Doctor");
|
|
3243
|
-
for (const check of checks) {
|
|
3409
|
+
for (const check of report.checks) {
|
|
3244
3410
|
console.log(`${check.ok ? "\u2713" : "\u2717"} ${check.name}: ${check.detail}`);
|
|
3245
3411
|
}
|
|
3246
3412
|
}
|
|
@@ -3642,7 +3808,7 @@ import {
|
|
|
3642
3808
|
import { startUiServer } from "@nextclaw/server";
|
|
3643
3809
|
import { appendFileSync, closeSync, cpSync as cpSync2, existsSync as existsSync10, mkdirSync as mkdirSync5, openSync } from "fs";
|
|
3644
3810
|
import { dirname as dirname2, join as join6, resolve as resolve10 } from "path";
|
|
3645
|
-
import { spawn as
|
|
3811
|
+
import { spawn as spawn3 } from "child_process";
|
|
3646
3812
|
import { request as httpRequest } from "http";
|
|
3647
3813
|
import { request as httpsRequest } from "https";
|
|
3648
3814
|
import { createServer as createNetServer2 } from "net";
|
|
@@ -3658,8 +3824,8 @@ import {
|
|
|
3658
3824
|
redactConfigObject
|
|
3659
3825
|
} from "@nextclaw/core";
|
|
3660
3826
|
var hashRaw = (raw) => createHash("sha256").update(raw).digest("hex");
|
|
3661
|
-
var readConfigSnapshot = (
|
|
3662
|
-
const path2 =
|
|
3827
|
+
var readConfigSnapshot = (getConfigPath9) => {
|
|
3828
|
+
const path2 = getConfigPath9();
|
|
3663
3829
|
let raw = "";
|
|
3664
3830
|
let parsed = {};
|
|
3665
3831
|
if (existsSync7(path2)) {
|
|
@@ -6368,6 +6534,325 @@ function writeReadyManagedServiceState(params) {
|
|
|
6368
6534
|
return state;
|
|
6369
6535
|
}
|
|
6370
6536
|
|
|
6537
|
+
// src/cli/commands/remote-access-host.ts
|
|
6538
|
+
import { getConfigPath as getConfigPath6, loadConfig as loadConfig13 } from "@nextclaw/core";
|
|
6539
|
+
import { spawn as spawn2 } from "child_process";
|
|
6540
|
+
var FORCED_PUBLIC_UI_HOST = "0.0.0.0";
|
|
6541
|
+
function normalizeOptionalString5(value) {
|
|
6542
|
+
if (typeof value !== "string") {
|
|
6543
|
+
return null;
|
|
6544
|
+
}
|
|
6545
|
+
const trimmed = value.trim();
|
|
6546
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
6547
|
+
}
|
|
6548
|
+
function decodeJwtPayload(token) {
|
|
6549
|
+
const segments = token.split(".");
|
|
6550
|
+
if (segments.length < 2) {
|
|
6551
|
+
return null;
|
|
6552
|
+
}
|
|
6553
|
+
try {
|
|
6554
|
+
const raw = Buffer.from(segments[1], "base64url").toString("utf-8");
|
|
6555
|
+
const parsed = JSON.parse(raw);
|
|
6556
|
+
return typeof parsed === "object" && parsed !== null ? parsed : null;
|
|
6557
|
+
} catch {
|
|
6558
|
+
return null;
|
|
6559
|
+
}
|
|
6560
|
+
}
|
|
6561
|
+
function isPlatformSessionToken2(token) {
|
|
6562
|
+
return typeof token === "string" && token.startsWith("nca.");
|
|
6563
|
+
}
|
|
6564
|
+
function toRemoteRuntimeView(runtime2) {
|
|
6565
|
+
if (!runtime2) {
|
|
6566
|
+
return null;
|
|
6567
|
+
}
|
|
6568
|
+
return {
|
|
6569
|
+
enabled: runtime2.enabled,
|
|
6570
|
+
mode: runtime2.mode,
|
|
6571
|
+
state: runtime2.state,
|
|
6572
|
+
deviceId: runtime2.deviceId,
|
|
6573
|
+
deviceName: runtime2.deviceName,
|
|
6574
|
+
platformBase: runtime2.platformBase,
|
|
6575
|
+
localOrigin: runtime2.localOrigin,
|
|
6576
|
+
lastConnectedAt: runtime2.lastConnectedAt,
|
|
6577
|
+
lastError: runtime2.lastError,
|
|
6578
|
+
updatedAt: runtime2.updatedAt
|
|
6579
|
+
};
|
|
6580
|
+
}
|
|
6581
|
+
var RemoteAccessHost = class {
|
|
6582
|
+
constructor(deps) {
|
|
6583
|
+
this.deps = deps;
|
|
6584
|
+
}
|
|
6585
|
+
getStatus() {
|
|
6586
|
+
const config2 = loadConfig13(getConfigPath6());
|
|
6587
|
+
const status = this.deps.remoteCommands.getStatusView();
|
|
6588
|
+
const serviceState = readServiceState();
|
|
6589
|
+
const serviceRunning = Boolean(serviceState && isProcessRunning(serviceState.pid));
|
|
6590
|
+
const account = this.readAccountView({
|
|
6591
|
+
token: normalizeOptionalString5(config2.providers.nextclaw?.apiKey),
|
|
6592
|
+
apiBase: normalizeOptionalString5(config2.providers.nextclaw?.apiBase),
|
|
6593
|
+
platformBase: status.platformBase
|
|
6594
|
+
});
|
|
6595
|
+
const service = {
|
|
6596
|
+
running: serviceRunning,
|
|
6597
|
+
currentProcess: Boolean(serviceRunning && serviceState?.pid === process.pid),
|
|
6598
|
+
...serviceState?.pid ? { pid: serviceState.pid } : {},
|
|
6599
|
+
...serviceState?.uiUrl ? { uiUrl: serviceState.uiUrl } : {},
|
|
6600
|
+
...typeof serviceState?.uiPort === "number" ? { uiPort: serviceState.uiPort } : {}
|
|
6601
|
+
};
|
|
6602
|
+
return {
|
|
6603
|
+
account,
|
|
6604
|
+
settings: {
|
|
6605
|
+
enabled: config2.remote.enabled,
|
|
6606
|
+
deviceName: config2.remote.deviceName,
|
|
6607
|
+
platformApiBase: config2.remote.platformApiBase
|
|
6608
|
+
},
|
|
6609
|
+
service,
|
|
6610
|
+
localOrigin: status.localOrigin,
|
|
6611
|
+
configuredEnabled: status.configuredEnabled,
|
|
6612
|
+
platformBase: status.platformBase,
|
|
6613
|
+
runtime: toRemoteRuntimeView(status.runtime)
|
|
6614
|
+
};
|
|
6615
|
+
}
|
|
6616
|
+
async login(input) {
|
|
6617
|
+
await this.deps.platformAuthCommands.loginResult(input);
|
|
6618
|
+
return this.getStatus();
|
|
6619
|
+
}
|
|
6620
|
+
async startBrowserAuth(input) {
|
|
6621
|
+
const result = await this.deps.platformAuthCommands.startBrowserAuth({
|
|
6622
|
+
apiBase: input.apiBase
|
|
6623
|
+
});
|
|
6624
|
+
return {
|
|
6625
|
+
sessionId: result.sessionId,
|
|
6626
|
+
verificationUri: result.verificationUri,
|
|
6627
|
+
expiresAt: result.expiresAt,
|
|
6628
|
+
intervalMs: result.intervalMs
|
|
6629
|
+
};
|
|
6630
|
+
}
|
|
6631
|
+
async pollBrowserAuth(input) {
|
|
6632
|
+
const config2 = loadConfig13(getConfigPath6());
|
|
6633
|
+
const result = await this.deps.platformAuthCommands.pollBrowserAuth({
|
|
6634
|
+
apiBase: normalizeOptionalString5(input.apiBase) ?? normalizeOptionalString5(config2.remote.platformApiBase) ?? normalizeOptionalString5(config2.providers.nextclaw?.apiBase) ?? void 0,
|
|
6635
|
+
sessionId: input.sessionId
|
|
6636
|
+
});
|
|
6637
|
+
if (result.status !== "authorized") {
|
|
6638
|
+
return result;
|
|
6639
|
+
}
|
|
6640
|
+
return {
|
|
6641
|
+
status: "authorized",
|
|
6642
|
+
email: result.email,
|
|
6643
|
+
role: result.role
|
|
6644
|
+
};
|
|
6645
|
+
}
|
|
6646
|
+
logout() {
|
|
6647
|
+
this.deps.platformAuthCommands.logout();
|
|
6648
|
+
return this.getStatus();
|
|
6649
|
+
}
|
|
6650
|
+
updateSettings(input) {
|
|
6651
|
+
this.deps.remoteCommands.updateConfig({
|
|
6652
|
+
enabled: input.enabled,
|
|
6653
|
+
apiBase: input.platformApiBase,
|
|
6654
|
+
name: input.deviceName
|
|
6655
|
+
});
|
|
6656
|
+
return this.getStatus();
|
|
6657
|
+
}
|
|
6658
|
+
async runDoctor() {
|
|
6659
|
+
const report = await this.deps.remoteCommands.getDoctorView();
|
|
6660
|
+
return {
|
|
6661
|
+
generatedAt: report.generatedAt,
|
|
6662
|
+
checks: report.checks,
|
|
6663
|
+
snapshot: {
|
|
6664
|
+
configuredEnabled: report.snapshot.configuredEnabled,
|
|
6665
|
+
runtime: toRemoteRuntimeView(report.snapshot.runtime)
|
|
6666
|
+
}
|
|
6667
|
+
};
|
|
6668
|
+
}
|
|
6669
|
+
async controlService(action) {
|
|
6670
|
+
const state = readServiceState();
|
|
6671
|
+
const running = Boolean(state && isProcessRunning(state.pid));
|
|
6672
|
+
const currentProcess = Boolean(running && state?.pid === process.pid);
|
|
6673
|
+
const uiOverrides = this.resolveManagedUiOverrides();
|
|
6674
|
+
if (action === "start") {
|
|
6675
|
+
if (running) {
|
|
6676
|
+
return {
|
|
6677
|
+
accepted: true,
|
|
6678
|
+
action,
|
|
6679
|
+
message: currentProcess ? "Managed service is already running for this UI." : "Managed service is already running."
|
|
6680
|
+
};
|
|
6681
|
+
}
|
|
6682
|
+
await this.deps.serviceCommands.startService({
|
|
6683
|
+
uiOverrides,
|
|
6684
|
+
open: false
|
|
6685
|
+
});
|
|
6686
|
+
return {
|
|
6687
|
+
accepted: true,
|
|
6688
|
+
action,
|
|
6689
|
+
message: "Managed service started."
|
|
6690
|
+
};
|
|
6691
|
+
}
|
|
6692
|
+
if (!running) {
|
|
6693
|
+
if (action === "restart") {
|
|
6694
|
+
await this.deps.serviceCommands.startService({
|
|
6695
|
+
uiOverrides,
|
|
6696
|
+
open: false
|
|
6697
|
+
});
|
|
6698
|
+
return {
|
|
6699
|
+
accepted: true,
|
|
6700
|
+
action,
|
|
6701
|
+
message: "Managed service was not running and has been started."
|
|
6702
|
+
};
|
|
6703
|
+
}
|
|
6704
|
+
return {
|
|
6705
|
+
accepted: true,
|
|
6706
|
+
action,
|
|
6707
|
+
message: "No managed service is currently running."
|
|
6708
|
+
};
|
|
6709
|
+
}
|
|
6710
|
+
if (currentProcess) {
|
|
6711
|
+
if (action === "restart") {
|
|
6712
|
+
await this.deps.requestManagedServiceRestart({
|
|
6713
|
+
uiPort: uiOverrides.port ?? 18791
|
|
6714
|
+
});
|
|
6715
|
+
} else {
|
|
6716
|
+
this.scheduleSelfStop();
|
|
6717
|
+
}
|
|
6718
|
+
return {
|
|
6719
|
+
accepted: true,
|
|
6720
|
+
action,
|
|
6721
|
+
message: action === "restart" ? "Restart scheduled. This page may disconnect for a few seconds." : "Stop scheduled. This page will disconnect shortly."
|
|
6722
|
+
};
|
|
6723
|
+
}
|
|
6724
|
+
if (action === "stop") {
|
|
6725
|
+
await this.deps.serviceCommands.stopService();
|
|
6726
|
+
return {
|
|
6727
|
+
accepted: true,
|
|
6728
|
+
action,
|
|
6729
|
+
message: "Managed service stopped."
|
|
6730
|
+
};
|
|
6731
|
+
}
|
|
6732
|
+
await this.deps.serviceCommands.stopService();
|
|
6733
|
+
await this.deps.serviceCommands.startService({
|
|
6734
|
+
uiOverrides,
|
|
6735
|
+
open: false
|
|
6736
|
+
});
|
|
6737
|
+
return {
|
|
6738
|
+
accepted: true,
|
|
6739
|
+
action,
|
|
6740
|
+
message: "Managed service restarted."
|
|
6741
|
+
};
|
|
6742
|
+
}
|
|
6743
|
+
resolveManagedUiOverrides() {
|
|
6744
|
+
const config2 = loadConfig13(getConfigPath6());
|
|
6745
|
+
const resolved = resolveUiConfig(config2, {
|
|
6746
|
+
enabled: true,
|
|
6747
|
+
host: FORCED_PUBLIC_UI_HOST,
|
|
6748
|
+
open: false
|
|
6749
|
+
});
|
|
6750
|
+
return {
|
|
6751
|
+
enabled: true,
|
|
6752
|
+
host: FORCED_PUBLIC_UI_HOST,
|
|
6753
|
+
open: false,
|
|
6754
|
+
port: resolved.port
|
|
6755
|
+
};
|
|
6756
|
+
}
|
|
6757
|
+
readAccountView(params) {
|
|
6758
|
+
if (!isPlatformSessionToken2(params.token)) {
|
|
6759
|
+
return {
|
|
6760
|
+
loggedIn: false,
|
|
6761
|
+
apiBase: params.apiBase,
|
|
6762
|
+
platformBase: params.platformBase
|
|
6763
|
+
};
|
|
6764
|
+
}
|
|
6765
|
+
const payload = decodeJwtPayload(params.token);
|
|
6766
|
+
const email = typeof payload?.email === "string" ? payload.email : void 0;
|
|
6767
|
+
const role = typeof payload?.role === "string" ? payload.role : void 0;
|
|
6768
|
+
return {
|
|
6769
|
+
loggedIn: true,
|
|
6770
|
+
email,
|
|
6771
|
+
role,
|
|
6772
|
+
apiBase: params.apiBase,
|
|
6773
|
+
platformBase: params.platformBase
|
|
6774
|
+
};
|
|
6775
|
+
}
|
|
6776
|
+
scheduleSelfStop() {
|
|
6777
|
+
this.launchManagedSelfControl();
|
|
6778
|
+
}
|
|
6779
|
+
launchManagedSelfControl(params = {}) {
|
|
6780
|
+
const script = [
|
|
6781
|
+
'const { spawn } = require("node:child_process");',
|
|
6782
|
+
'const { rmSync } = require("node:fs");',
|
|
6783
|
+
`const parentPid = ${process.pid};`,
|
|
6784
|
+
`const serviceStatePath = ${JSON.stringify(resolveServiceStatePath())};`,
|
|
6785
|
+
`const command = ${JSON.stringify(params.command ?? null)};`,
|
|
6786
|
+
`const args = ${JSON.stringify(params.args ?? [])};`,
|
|
6787
|
+
`const cwd = ${JSON.stringify(process.cwd())};`,
|
|
6788
|
+
"const env = process.env;",
|
|
6789
|
+
"function isRunning(pid) {",
|
|
6790
|
+
" try {",
|
|
6791
|
+
" process.kill(pid, 0);",
|
|
6792
|
+
" return true;",
|
|
6793
|
+
" } catch {",
|
|
6794
|
+
" return false;",
|
|
6795
|
+
" }",
|
|
6796
|
+
"}",
|
|
6797
|
+
"setTimeout(() => {",
|
|
6798
|
+
" try {",
|
|
6799
|
+
" process.kill(parentPid, 'SIGTERM');",
|
|
6800
|
+
" } catch {}",
|
|
6801
|
+
"}, 150);",
|
|
6802
|
+
"const startedAt = Date.now();",
|
|
6803
|
+
"const maxWaitMs = 30000;",
|
|
6804
|
+
"const timer = setInterval(() => {",
|
|
6805
|
+
" if (isRunning(parentPid)) {",
|
|
6806
|
+
" if (Date.now() - startedAt > maxWaitMs) {",
|
|
6807
|
+
" try {",
|
|
6808
|
+
" process.kill(parentPid, 'SIGKILL');",
|
|
6809
|
+
" } catch {}",
|
|
6810
|
+
" }",
|
|
6811
|
+
" return;",
|
|
6812
|
+
" }",
|
|
6813
|
+
" clearInterval(timer);",
|
|
6814
|
+
" try {",
|
|
6815
|
+
" rmSync(serviceStatePath, { force: true });",
|
|
6816
|
+
" } catch {}",
|
|
6817
|
+
" if (command) {",
|
|
6818
|
+
" const child = spawn(command, args, { detached: true, stdio: 'ignore', cwd, env });",
|
|
6819
|
+
" child.unref();",
|
|
6820
|
+
" }",
|
|
6821
|
+
" process.exit(0);",
|
|
6822
|
+
"}, 250);"
|
|
6823
|
+
].join("");
|
|
6824
|
+
const helper = spawn2(process.execPath, ["-e", script], {
|
|
6825
|
+
detached: true,
|
|
6826
|
+
stdio: "ignore",
|
|
6827
|
+
env: process.env,
|
|
6828
|
+
cwd: process.cwd()
|
|
6829
|
+
});
|
|
6830
|
+
helper.unref();
|
|
6831
|
+
}
|
|
6832
|
+
};
|
|
6833
|
+
|
|
6834
|
+
// src/cli/commands/service-remote-access.ts
|
|
6835
|
+
function requestManagedServiceRestart(requestRestart, options = {}) {
|
|
6836
|
+
const uiPort = typeof options.uiPort === "number" && Number.isFinite(options.uiPort) ? Math.floor(options.uiPort) : void 0;
|
|
6837
|
+
const reason = options.reason?.trim() || "remote access service restart";
|
|
6838
|
+
const manualMessage = uiPort ? `Restart the managed service to restore the UI on port ${uiPort}.` : "Restart the managed service to restore the UI.";
|
|
6839
|
+
return requestRestart({
|
|
6840
|
+
reason,
|
|
6841
|
+
manualMessage,
|
|
6842
|
+
strategy: "background-service-or-exit",
|
|
6843
|
+
delayMs: 500,
|
|
6844
|
+
silentOnServiceRestart: true
|
|
6845
|
+
});
|
|
6846
|
+
}
|
|
6847
|
+
function createRemoteAccessHost(params) {
|
|
6848
|
+
return new RemoteAccessHost({
|
|
6849
|
+
serviceCommands: params.serviceCommands,
|
|
6850
|
+
requestManagedServiceRestart: (options) => requestManagedServiceRestart(params.requestRestart, options),
|
|
6851
|
+
remoteCommands: new RemoteCommands(),
|
|
6852
|
+
platformAuthCommands: new PlatformAuthCommands()
|
|
6853
|
+
});
|
|
6854
|
+
}
|
|
6855
|
+
|
|
6371
6856
|
// src/cli/commands/ui-chat-run-coordinator.ts
|
|
6372
6857
|
import { existsSync as existsSync9, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
|
|
6373
6858
|
import { join as join5 } from "path";
|
|
@@ -6992,14 +7477,14 @@ var {
|
|
|
6992
7477
|
ChannelManager: ChannelManager2,
|
|
6993
7478
|
CronService: CronService2,
|
|
6994
7479
|
getApiBase,
|
|
6995
|
-
getConfigPath:
|
|
7480
|
+
getConfigPath: getConfigPath7,
|
|
6996
7481
|
getDataDir: getDataDir7,
|
|
6997
7482
|
getProvider,
|
|
6998
7483
|
getProviderName,
|
|
6999
7484
|
getWorkspacePath: getWorkspacePath9,
|
|
7000
7485
|
HeartbeatService,
|
|
7001
7486
|
LiteLLMProvider,
|
|
7002
|
-
loadConfig:
|
|
7487
|
+
loadConfig: loadConfig14,
|
|
7003
7488
|
MessageBus,
|
|
7004
7489
|
ProviderManager,
|
|
7005
7490
|
resolveConfigSecrets: resolveConfigSecrets2,
|
|
@@ -7023,8 +7508,8 @@ var ServiceCommands = class {
|
|
|
7023
7508
|
async startGateway(options = {}) {
|
|
7024
7509
|
this.applyLiveConfigReload = null;
|
|
7025
7510
|
this.liveUiNcpAgent = null;
|
|
7026
|
-
const runtimeConfigPath =
|
|
7027
|
-
const config2 = resolveConfigSecrets2(
|
|
7511
|
+
const runtimeConfigPath = getConfigPath7();
|
|
7512
|
+
const config2 = resolveConfigSecrets2(loadConfig14(), { configPath: runtimeConfigPath });
|
|
7028
7513
|
const workspace = getWorkspacePath9(config2.agents.defaults.workspace);
|
|
7029
7514
|
let pluginRegistry = loadPluginRegistry(config2, workspace);
|
|
7030
7515
|
let extensionRegistry = toExtensionRegistry(pluginRegistry);
|
|
@@ -7053,7 +7538,7 @@ var ServiceCommands = class {
|
|
|
7053
7538
|
sessionManager,
|
|
7054
7539
|
providerManager,
|
|
7055
7540
|
makeProvider: (nextConfig) => this.makeProvider(nextConfig, { allowMissing: true }) ?? this.makeMissingProvider(nextConfig),
|
|
7056
|
-
loadConfig: () => resolveConfigSecrets2(
|
|
7541
|
+
loadConfig: () => resolveConfigSecrets2(loadConfig14(), { configPath: runtimeConfigPath }),
|
|
7057
7542
|
getExtensionChannels: () => extensionRegistry.channels,
|
|
7058
7543
|
onRestartRequired: (paths) => {
|
|
7059
7544
|
void this.deps.requestRestart({
|
|
@@ -7064,13 +7549,13 @@ var ServiceCommands = class {
|
|
|
7064
7549
|
}
|
|
7065
7550
|
});
|
|
7066
7551
|
this.applyLiveConfigReload = async () => {
|
|
7067
|
-
await reloader.applyReloadPlan(resolveConfigSecrets2(
|
|
7552
|
+
await reloader.applyReloadPlan(resolveConfigSecrets2(loadConfig14(), { configPath: runtimeConfigPath }));
|
|
7068
7553
|
};
|
|
7069
7554
|
const gatewayController = new GatewayControllerImpl({
|
|
7070
7555
|
reloader,
|
|
7071
7556
|
cron: cron2,
|
|
7072
7557
|
sessionManager,
|
|
7073
|
-
getConfigPath:
|
|
7558
|
+
getConfigPath: getConfigPath7,
|
|
7074
7559
|
saveConfig: saveConfig9,
|
|
7075
7560
|
requestRestart: async (options2) => {
|
|
7076
7561
|
await this.deps.requestRestart({
|
|
@@ -7097,7 +7582,7 @@ var ServiceCommands = class {
|
|
|
7097
7582
|
resolveMessageToolHints: ({ channel, accountId }) => resolvePluginChannelMessageToolHints({
|
|
7098
7583
|
registry: pluginRegistry,
|
|
7099
7584
|
channel,
|
|
7100
|
-
cfg: resolveConfigSecrets2(
|
|
7585
|
+
cfg: resolveConfigSecrets2(loadConfig14(), { configPath: runtimeConfigPath }),
|
|
7101
7586
|
accountId
|
|
7102
7587
|
})
|
|
7103
7588
|
});
|
|
@@ -7130,12 +7615,12 @@ var ServiceCommands = class {
|
|
|
7130
7615
|
});
|
|
7131
7616
|
let pluginChannelBindings = getPluginChannelBindings3(pluginRegistry);
|
|
7132
7617
|
setPluginRuntimeBridge({
|
|
7133
|
-
loadConfig: () => toPluginConfigView(resolveConfigSecrets2(
|
|
7618
|
+
loadConfig: () => toPluginConfigView(resolveConfigSecrets2(loadConfig14(), { configPath: runtimeConfigPath }), pluginChannelBindings),
|
|
7134
7619
|
writeConfigFile: async (nextConfigView) => {
|
|
7135
7620
|
if (!nextConfigView || typeof nextConfigView !== "object" || Array.isArray(nextConfigView)) {
|
|
7136
7621
|
throw new Error("plugin runtime writeConfigFile expects an object config");
|
|
7137
7622
|
}
|
|
7138
|
-
const current =
|
|
7623
|
+
const current = loadConfig14();
|
|
7139
7624
|
const next = mergePluginConfigView(current, nextConfigView, pluginChannelBindings);
|
|
7140
7625
|
saveConfig9(next);
|
|
7141
7626
|
},
|
|
@@ -7211,12 +7696,12 @@ var ServiceCommands = class {
|
|
|
7211
7696
|
providerManager,
|
|
7212
7697
|
bus,
|
|
7213
7698
|
gatewayController,
|
|
7214
|
-
() => resolveConfigSecrets2(
|
|
7699
|
+
() => resolveConfigSecrets2(loadConfig14(), { configPath: runtimeConfigPath }),
|
|
7215
7700
|
() => extensionRegistry,
|
|
7216
7701
|
({ channel, accountId }) => resolvePluginChannelMessageToolHints({
|
|
7217
7702
|
registry: pluginRegistry,
|
|
7218
7703
|
channel,
|
|
7219
|
-
cfg: resolveConfigSecrets2(
|
|
7704
|
+
cfg: resolveConfigSecrets2(loadConfig14(), { configPath: runtimeConfigPath }),
|
|
7220
7705
|
accountId
|
|
7221
7706
|
})
|
|
7222
7707
|
);
|
|
@@ -7254,7 +7739,7 @@ var ServiceCommands = class {
|
|
|
7254
7739
|
return trimmed || void 0;
|
|
7255
7740
|
}
|
|
7256
7741
|
watchConfigFile(reloader) {
|
|
7257
|
-
const configPath = resolve10(
|
|
7742
|
+
const configPath = resolve10(getConfigPath7());
|
|
7258
7743
|
const watcher = chokidar.watch(configPath, {
|
|
7259
7744
|
ignoreInitial: true,
|
|
7260
7745
|
awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 }
|
|
@@ -7375,7 +7860,7 @@ var ServiceCommands = class {
|
|
|
7375
7860
|
});
|
|
7376
7861
|
}
|
|
7377
7862
|
async runForeground(options) {
|
|
7378
|
-
const config2 =
|
|
7863
|
+
const config2 = loadConfig14();
|
|
7379
7864
|
const uiConfig = resolveUiConfig(config2, options.uiOverrides);
|
|
7380
7865
|
const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
|
|
7381
7866
|
if (options.open) {
|
|
@@ -7388,7 +7873,7 @@ var ServiceCommands = class {
|
|
|
7388
7873
|
});
|
|
7389
7874
|
}
|
|
7390
7875
|
async startService(options) {
|
|
7391
|
-
const config2 =
|
|
7876
|
+
const config2 = loadConfig14();
|
|
7392
7877
|
const uiConfig = resolveUiConfig(config2, options.uiOverrides);
|
|
7393
7878
|
const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
|
|
7394
7879
|
const apiUrl = `${uiUrl}/api`;
|
|
@@ -7461,7 +7946,7 @@ var ServiceCommands = class {
|
|
|
7461
7946
|
console.log(`Starting ${APP_NAME3} background service (readiness timeout ${Math.ceil(readinessTimeoutMs / 1e3)}s)...`);
|
|
7462
7947
|
const serveArgs = buildServeArgs({ uiPort: uiConfig.port });
|
|
7463
7948
|
this.appendStartupStage(logPath, `spawning background process: ${process.execPath} ${[...process.execArgv, ...serveArgs].join(" ")}`);
|
|
7464
|
-
const child =
|
|
7949
|
+
const child = spawn3(process.execPath, [...process.execArgv, ...serveArgs], {
|
|
7465
7950
|
env: process.env,
|
|
7466
7951
|
stdio: ["ignore", logFd, logFd],
|
|
7467
7952
|
detached: true
|
|
@@ -7796,7 +8281,7 @@ var ServiceCommands = class {
|
|
|
7796
8281
|
return null;
|
|
7797
8282
|
}
|
|
7798
8283
|
console.error("Error: No API key configured.");
|
|
7799
|
-
console.error(`Set one in ${
|
|
8284
|
+
console.error(`Set one in ${getConfigPath7()} under providers section`);
|
|
7800
8285
|
process.exit(1);
|
|
7801
8286
|
}
|
|
7802
8287
|
return new LiteLLMProvider({
|
|
@@ -7909,10 +8394,7 @@ var ServiceCommands = class {
|
|
|
7909
8394
|
gatewayController,
|
|
7910
8395
|
getConfig,
|
|
7911
8396
|
getExtensionRegistry,
|
|
7912
|
-
resolveMessageToolHints: ({ channel, accountId }) => resolveMessageToolHints({
|
|
7913
|
-
channel,
|
|
7914
|
-
accountId
|
|
7915
|
-
})
|
|
8397
|
+
resolveMessageToolHints: ({ channel, accountId }) => resolveMessageToolHints({ channel, accountId })
|
|
7916
8398
|
});
|
|
7917
8399
|
this.liveUiNcpAgent = ncpAgent;
|
|
7918
8400
|
const marketplaceInstaller = new ServiceMarketplaceInstaller({
|
|
@@ -7920,10 +8402,11 @@ var ServiceCommands = class {
|
|
|
7920
8402
|
runCliSubcommand: (args) => this.runCliSubcommand(args),
|
|
7921
8403
|
installBuiltinSkill: (slug, force) => this.installBuiltinMarketplaceSkill(slug, force)
|
|
7922
8404
|
}).createInstaller();
|
|
8405
|
+
const remoteAccess = createRemoteAccessHost({ serviceCommands: this, requestRestart: this.deps.requestRestart });
|
|
7923
8406
|
const uiServer = startUiServer({
|
|
7924
8407
|
host: uiConfig.host,
|
|
7925
8408
|
port: uiConfig.port,
|
|
7926
|
-
configPath:
|
|
8409
|
+
configPath: getConfigPath7(),
|
|
7927
8410
|
productVersion: getPackageVersion(),
|
|
7928
8411
|
staticDir: uiStaticDir ?? void 0,
|
|
7929
8412
|
cronService,
|
|
@@ -7931,6 +8414,7 @@ var ServiceCommands = class {
|
|
|
7931
8414
|
apiBaseUrl: process.env.NEXTCLAW_MARKETPLACE_API_BASE,
|
|
7932
8415
|
installer: marketplaceInstaller
|
|
7933
8416
|
},
|
|
8417
|
+
remoteAccess,
|
|
7934
8418
|
ncpAgent,
|
|
7935
8419
|
chatRuntime: {
|
|
7936
8420
|
listSessionTypes: async () => {
|
|
@@ -8011,7 +8495,7 @@ var ServiceCommands = class {
|
|
|
8011
8495
|
}
|
|
8012
8496
|
}
|
|
8013
8497
|
installBuiltinMarketplaceSkill(slug, force) {
|
|
8014
|
-
const workspace = getWorkspacePath9(
|
|
8498
|
+
const workspace = getWorkspacePath9(loadConfig14().agents.defaults.workspace);
|
|
8015
8499
|
const destination = join6(workspace, "skills", slug);
|
|
8016
8500
|
const destinationSkillFile = join6(destination, "SKILL.md");
|
|
8017
8501
|
if (existsSync10(destinationSkillFile) && !force) {
|
|
@@ -8052,7 +8536,7 @@ ${stderr}`.trim();
|
|
|
8052
8536
|
runCommand(command, args, options = {}) {
|
|
8053
8537
|
const timeoutMs = options.timeoutMs ?? 18e4;
|
|
8054
8538
|
return new Promise((resolvePromise, rejectPromise) => {
|
|
8055
|
-
const child =
|
|
8539
|
+
const child = spawn3(command, args, {
|
|
8056
8540
|
cwd: options.cwd ?? process.cwd(),
|
|
8057
8541
|
env: process.env,
|
|
8058
8542
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -8270,7 +8754,7 @@ var WorkspaceManager = class {
|
|
|
8270
8754
|
// src/cli/runtime.ts
|
|
8271
8755
|
var LOGO = "\u{1F916}";
|
|
8272
8756
|
var EXIT_COMMANDS = /* @__PURE__ */ new Set(["exit", "quit", "/exit", "/quit", ":q"]);
|
|
8273
|
-
var
|
|
8757
|
+
var FORCED_PUBLIC_UI_HOST2 = "0.0.0.0";
|
|
8274
8758
|
function resolveSkillsInstallWorkdir(params) {
|
|
8275
8759
|
if (params.explicitWorkdir) {
|
|
8276
8760
|
return expandHome2(params.explicitWorkdir);
|
|
@@ -8350,7 +8834,7 @@ var CliRuntime = class {
|
|
|
8350
8834
|
if (!state || !isProcessRunning(state.pid) || state.pid === process.pid) {
|
|
8351
8835
|
return false;
|
|
8352
8836
|
}
|
|
8353
|
-
const uiHost =
|
|
8837
|
+
const uiHost = FORCED_PUBLIC_UI_HOST2;
|
|
8354
8838
|
const uiPort = typeof state.uiPort === "number" && Number.isFinite(state.uiPort) ? state.uiPort : 18791;
|
|
8355
8839
|
console.log(
|
|
8356
8840
|
`Applying changes (${reason}): restarting ${APP_NAME5} background service...`
|
|
@@ -8447,7 +8931,7 @@ var CliRuntime = class {
|
|
|
8447
8931
|
"}, delayMs);"
|
|
8448
8932
|
].join("\n");
|
|
8449
8933
|
try {
|
|
8450
|
-
const helper =
|
|
8934
|
+
const helper = spawn4(process.execPath, ["-e", helperScript], {
|
|
8451
8935
|
detached: true,
|
|
8452
8936
|
stdio: "ignore",
|
|
8453
8937
|
env: process.env
|
|
@@ -8516,14 +9000,14 @@ var CliRuntime = class {
|
|
|
8516
9000
|
const source = options.source ?? "init";
|
|
8517
9001
|
const prefix = options.auto ? "Auto init" : "Init";
|
|
8518
9002
|
const force = Boolean(options.force);
|
|
8519
|
-
const configPath =
|
|
9003
|
+
const configPath = getConfigPath8();
|
|
8520
9004
|
let createdConfig = false;
|
|
8521
9005
|
if (!existsSync12(configPath)) {
|
|
8522
9006
|
const config3 = ConfigSchema2.parse({});
|
|
8523
9007
|
saveConfig10(config3);
|
|
8524
9008
|
createdConfig = true;
|
|
8525
9009
|
}
|
|
8526
|
-
const config2 =
|
|
9010
|
+
const config2 = loadConfig15();
|
|
8527
9011
|
const workspaceSetting = config2.agents.defaults.workspace;
|
|
8528
9012
|
const workspacePath = !workspaceSetting || workspaceSetting === DEFAULT_WORKSPACE_PATH ? join8(getDataDir9(), DEFAULT_WORKSPACE_DIR) : expandHome2(workspaceSetting);
|
|
8529
9013
|
const workspaceExisted = existsSync12(workspacePath);
|
|
@@ -8562,7 +9046,7 @@ ${this.logo} ${APP_NAME5} is ready! (${source})`);
|
|
|
8562
9046
|
}
|
|
8563
9047
|
async gateway(opts) {
|
|
8564
9048
|
const uiOverrides = {
|
|
8565
|
-
host:
|
|
9049
|
+
host: FORCED_PUBLIC_UI_HOST2
|
|
8566
9050
|
};
|
|
8567
9051
|
if (opts.ui) {
|
|
8568
9052
|
uiOverrides.enabled = true;
|
|
@@ -8578,7 +9062,7 @@ ${this.logo} ${APP_NAME5} is ready! (${source})`);
|
|
|
8578
9062
|
async ui(opts) {
|
|
8579
9063
|
const uiOverrides = {
|
|
8580
9064
|
enabled: true,
|
|
8581
|
-
host:
|
|
9065
|
+
host: FORCED_PUBLIC_UI_HOST2,
|
|
8582
9066
|
open: Boolean(opts.open)
|
|
8583
9067
|
};
|
|
8584
9068
|
if (opts.port) {
|
|
@@ -8594,7 +9078,7 @@ ${this.logo} ${APP_NAME5} is ready! (${source})`);
|
|
|
8594
9078
|
await this.init({ source: "start", auto: true });
|
|
8595
9079
|
const uiOverrides = {
|
|
8596
9080
|
enabled: true,
|
|
8597
|
-
host:
|
|
9081
|
+
host: FORCED_PUBLIC_UI_HOST2,
|
|
8598
9082
|
open: false
|
|
8599
9083
|
};
|
|
8600
9084
|
if (opts.uiPort) {
|
|
@@ -8623,7 +9107,7 @@ ${this.logo} ${APP_NAME5} is ready! (${source})`);
|
|
|
8623
9107
|
async serve(opts) {
|
|
8624
9108
|
const uiOverrides = {
|
|
8625
9109
|
enabled: true,
|
|
8626
|
-
host:
|
|
9110
|
+
host: FORCED_PUBLIC_UI_HOST2,
|
|
8627
9111
|
open: false
|
|
8628
9112
|
};
|
|
8629
9113
|
if (opts.uiPort) {
|
|
@@ -8649,8 +9133,8 @@ ${this.logo} ${APP_NAME5} is ready! (${source})`);
|
|
|
8649
9133
|
await this.serviceCommands.stopService();
|
|
8650
9134
|
}
|
|
8651
9135
|
async agent(opts) {
|
|
8652
|
-
const configPath =
|
|
8653
|
-
const config2 = resolveConfigSecrets3(
|
|
9136
|
+
const configPath = getConfigPath8();
|
|
9137
|
+
const config2 = resolveConfigSecrets3(loadConfig15(), { configPath });
|
|
8654
9138
|
const workspace = getWorkspacePath10(config2.agents.defaults.workspace);
|
|
8655
9139
|
const pluginRegistry = loadPluginRegistry(config2, workspace);
|
|
8656
9140
|
const extensionRegistry = toExtensionRegistry(pluginRegistry);
|
|
@@ -8658,7 +9142,7 @@ ${this.logo} ${APP_NAME5} is ready! (${source})`);
|
|
|
8658
9142
|
const pluginChannelBindings = getPluginChannelBindings4(pluginRegistry);
|
|
8659
9143
|
setPluginRuntimeBridge2({
|
|
8660
9144
|
loadConfig: () => toPluginConfigView(
|
|
8661
|
-
resolveConfigSecrets3(
|
|
9145
|
+
resolveConfigSecrets3(loadConfig15(), { configPath }),
|
|
8662
9146
|
pluginChannelBindings
|
|
8663
9147
|
),
|
|
8664
9148
|
writeConfigFile: async (nextConfigView) => {
|
|
@@ -8667,7 +9151,7 @@ ${this.logo} ${APP_NAME5} is ready! (${source})`);
|
|
|
8667
9151
|
"plugin runtime writeConfigFile expects an object config"
|
|
8668
9152
|
);
|
|
8669
9153
|
}
|
|
8670
|
-
const current =
|
|
9154
|
+
const current = loadConfig15();
|
|
8671
9155
|
const next = mergePluginConfigView(
|
|
8672
9156
|
current,
|
|
8673
9157
|
nextConfigView,
|
|
@@ -8699,7 +9183,7 @@ ${this.logo} ${APP_NAME5} is ready! (${source})`);
|
|
|
8699
9183
|
resolveMessageToolHints: ({ channel, accountId }) => resolvePluginChannelMessageToolHints2({
|
|
8700
9184
|
registry: pluginRegistry,
|
|
8701
9185
|
channel,
|
|
8702
|
-
cfg: resolveConfigSecrets3(
|
|
9186
|
+
cfg: resolveConfigSecrets3(loadConfig15(), { configPath }),
|
|
8703
9187
|
accountId
|
|
8704
9188
|
})
|
|
8705
9189
|
});
|
|
@@ -8894,7 +9378,7 @@ ${this.logo} ${APP_NAME5} is ready! (${source})`);
|
|
|
8894
9378
|
await this.diagnosticsCommands.doctor(opts);
|
|
8895
9379
|
}
|
|
8896
9380
|
async skillsInstall(options) {
|
|
8897
|
-
const config2 =
|
|
9381
|
+
const config2 = loadConfig15();
|
|
8898
9382
|
const workdir = resolveSkillsInstallWorkdir({
|
|
8899
9383
|
explicitWorkdir: options.workdir,
|
|
8900
9384
|
configuredWorkspace: config2.agents.defaults.workspace
|