nextclaw 0.13.4 → 0.13.6

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.
Files changed (2) hide show
  1. package/dist/cli/index.js +219 -797
  2. package/package.json +8 -7
package/dist/cli/index.js CHANGED
@@ -2,11 +2,12 @@
2
2
 
3
3
  // src/cli/index.ts
4
4
  import { Command } from "commander";
5
- import { APP_NAME as APP_NAME7, APP_TAGLINE } from "@nextclaw/core";
5
+ import { APP_NAME as APP_NAME6, APP_TAGLINE } from "@nextclaw/core";
6
+ import { registerRemoteCommands } from "@nextclaw/remote";
6
7
 
7
8
  // src/cli/runtime.ts
8
9
  import {
9
- loadConfig as loadConfig15,
10
+ loadConfig as loadConfig14,
10
11
  saveConfig as saveConfig10,
11
12
  getConfigPath as getConfigPath7,
12
13
  getDataDir as getDataDir9,
@@ -17,17 +18,18 @@ import {
17
18
  AgentLoop,
18
19
  ProviderManager as ProviderManager2,
19
20
  resolveConfigSecrets as resolveConfigSecrets3,
20
- APP_NAME as APP_NAME6,
21
+ APP_NAME as APP_NAME5,
21
22
  DEFAULT_WORKSPACE_DIR,
22
23
  DEFAULT_WORKSPACE_PATH
23
24
  } from "@nextclaw/core";
25
+ import { RemoteRuntimeActions } from "@nextclaw/remote";
24
26
  import {
25
27
  getPluginChannelBindings as getPluginChannelBindings4,
26
28
  resolvePluginChannelMessageToolHints as resolvePluginChannelMessageToolHints2,
27
29
  setPluginRuntimeBridge as setPluginRuntimeBridge2
28
30
  } from "@nextclaw/openclaw-compat";
29
- import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
30
- import { join as join9, resolve as resolve12 } from "path";
31
+ import { existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
32
+ import { join as join8, resolve as resolve12 } from "path";
31
33
  import { createInterface as createInterface3 } from "readline";
32
34
  import { fileURLToPath as fileURLToPath5 } from "url";
33
35
  import { spawn as spawn3 } from "child_process";
@@ -74,9 +76,9 @@ var RestartCoordinator = class {
74
76
  message: "Restart already scheduled; skipping duplicate request."
75
77
  };
76
78
  }
77
- const delay2 = typeof request.delayMs === "number" && Number.isFinite(request.delayMs) ? Math.max(0, Math.floor(request.delayMs)) : 100;
79
+ const delay = typeof request.delayMs === "number" && Number.isFinite(request.delayMs) ? Math.max(0, Math.floor(request.delayMs)) : 100;
78
80
  this.exitScheduled = true;
79
- this.deps.scheduleProcessExit(delay2, reason);
81
+ this.deps.scheduleProcessExit(delay, reason);
80
82
  return {
81
83
  status: "exit-scheduled",
82
84
  message: `Restart scheduled (${reason}).`
@@ -3034,541 +3036,72 @@ var PlatformAuthCommands = class {
3034
3036
  };
3035
3037
 
3036
3038
  // src/cli/commands/remote.ts
3037
- import { getConfigPath as getConfigPath4, loadConfig as loadConfig10, saveConfig as saveConfig7 } from "@nextclaw/core";
3038
- import { hostname as hostname3 } from "os";
3039
+ import { getConfigPath as getConfigPath4, loadConfig as loadConfig9, saveConfig as saveConfig7 } from "@nextclaw/core";
3040
+ import "@nextclaw/remote";
3041
+ import { hostname } from "os";
3039
3042
 
3040
- // src/cli/remote/remote-relay-bridge.ts
3041
- import { ensureUiBridgeSecret } from "@nextclaw/server";
3042
- function encodeBase64(bytes) {
3043
- return Buffer.from(bytes).toString("base64");
3044
- }
3045
- function decodeBase64(base64) {
3046
- if (!base64) {
3047
- return new Uint8Array();
3048
- }
3049
- return new Uint8Array(Buffer.from(base64, "base64"));
3050
- }
3051
- var RemoteRelayBridge = class {
3052
- constructor(localOrigin) {
3053
- this.localOrigin = localOrigin;
3054
- }
3055
- async ensureLocalUiHealthy() {
3056
- const response = await fetch(`${this.localOrigin}/api/health`);
3057
- if (!response.ok) {
3058
- throw new Error(`Local UI is not healthy at ${this.localOrigin}. Start NextClaw first.`);
3059
- }
3060
- }
3061
- async forward(frame, socket) {
3062
- const bridgeCookie = await this.requestBridgeCookie();
3063
- const url = new URL(frame.path, this.localOrigin);
3064
- const headers = this.createForwardHeaders(frame.headers, bridgeCookie);
3065
- const response = await fetch(url, {
3066
- method: frame.method,
3067
- headers,
3068
- body: frame.method === "GET" || frame.method === "HEAD" ? void 0 : decodeBase64(frame.bodyBase64)
3069
- });
3070
- const responseHeaders = Array.from(response.headers.entries()).filter(([key]) => {
3071
- const lower = key.toLowerCase();
3072
- return !["content-length", "connection", "transfer-encoding", "set-cookie"].includes(lower);
3073
- });
3074
- const contentType = response.headers.get("content-type")?.toLowerCase() ?? "";
3075
- if (response.body && contentType.startsWith("text/event-stream")) {
3076
- await this.sendStreamingResponse({ frame, response, responseHeaders, socket });
3077
- return;
3078
- }
3079
- const responseBody = response.body ? new Uint8Array(await response.arrayBuffer()) : new Uint8Array();
3080
- socket.send(JSON.stringify({
3081
- type: "response",
3082
- requestId: frame.requestId,
3083
- status: response.status,
3084
- headers: responseHeaders,
3085
- bodyBase64: encodeBase64(responseBody)
3086
- }));
3087
- }
3088
- createForwardHeaders(headersList, bridgeCookie) {
3089
- const headers = new Headers();
3090
- for (const [key, value] of headersList) {
3091
- const lower = key.toLowerCase();
3092
- if ([
3093
- "host",
3094
- "connection",
3095
- "content-length",
3096
- "cookie",
3097
- "x-forwarded-for",
3098
- "x-forwarded-proto",
3099
- "cf-connecting-ip"
3100
- ].includes(lower)) {
3101
- continue;
3102
- }
3103
- headers.set(key, value);
3104
- }
3105
- if (bridgeCookie) {
3106
- headers.set("cookie", bridgeCookie);
3107
- }
3108
- return headers;
3109
- }
3110
- async requestBridgeCookie() {
3111
- const response = await fetch(`${this.localOrigin}/api/auth/bridge`, {
3112
- method: "POST",
3113
- headers: {
3114
- "x-nextclaw-ui-bridge-secret": ensureUiBridgeSecret()
3115
- }
3116
- });
3117
- const payload = await response.json();
3118
- if (!response.ok || !payload.ok) {
3119
- throw new Error(payload.error?.message ?? `Failed to request local auth bridge (${response.status}).`);
3120
- }
3121
- return typeof payload.data?.cookie === "string" && payload.data.cookie.trim().length > 0 ? payload.data.cookie.trim() : null;
3122
- }
3123
- async sendStreamingResponse(params) {
3124
- params.socket.send(JSON.stringify({
3125
- type: "response.start",
3126
- requestId: params.frame.requestId,
3127
- status: params.response.status,
3128
- headers: params.responseHeaders
3129
- }));
3130
- const reader = params.response.body?.getReader();
3131
- if (!reader) {
3132
- params.socket.send(JSON.stringify({
3133
- type: "response.end",
3134
- requestId: params.frame.requestId
3135
- }));
3136
- return;
3137
- }
3138
- try {
3139
- while (true) {
3140
- const { value, done } = await reader.read();
3141
- if (done) {
3142
- break;
3143
- }
3144
- if (value && value.length > 0) {
3145
- params.socket.send(JSON.stringify({
3146
- type: "response.chunk",
3147
- requestId: params.frame.requestId,
3148
- bodyBase64: encodeBase64(value)
3149
- }));
3150
- }
3151
- }
3152
- } finally {
3153
- reader.releaseLock();
3154
- }
3155
- params.socket.send(JSON.stringify({
3156
- type: "response.end",
3157
- requestId: params.frame.requestId
3158
- }));
3159
- }
3160
- };
3161
-
3162
- // src/cli/remote/remote-platform-client.ts
3043
+ // src/cli/commands/remote-runtime-support.ts
3163
3044
  import { getConfigPath as getConfigPath3, getDataDir as getDataDir4, loadConfig as loadConfig8 } from "@nextclaw/core";
3164
- import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
3165
- import { dirname as dirname2, join as join4 } from "path";
3166
- import { hostname, platform as readPlatform } from "os";
3167
- function ensureDir(path2) {
3168
- mkdirSync4(path2, { recursive: true });
3169
- }
3170
- function readJsonFile2(path2) {
3171
- if (!existsSync6(path2)) {
3172
- return null;
3173
- }
3174
- try {
3175
- return JSON.parse(readFileSync6(path2, "utf-8"));
3176
- } catch {
3177
- return null;
3178
- }
3179
- }
3180
- function writeJsonFile(path2, value) {
3181
- ensureDir(dirname2(path2));
3182
- writeFileSync4(path2, `${JSON.stringify(value, null, 2)}
3183
- `, "utf-8");
3184
- }
3185
- function maskToken(value) {
3186
- if (value.length <= 12) {
3187
- return "<redacted>";
3188
- }
3189
- return `${value.slice(0, 6)}...${value.slice(-4)}`;
3190
- }
3191
- function normalizeOptionalString3(value) {
3192
- if (typeof value !== "string") {
3193
- return void 0;
3194
- }
3195
- const trimmed = value.trim();
3196
- return trimmed.length > 0 ? trimmed : void 0;
3045
+ import {
3046
+ RemoteConnector,
3047
+ RemotePlatformClient,
3048
+ RemoteStatusStore,
3049
+ buildConfiguredRemoteState,
3050
+ resolveRemoteStatusSnapshot
3051
+ } from "@nextclaw/remote";
3052
+ function createNextclawRemotePlatformClient() {
3053
+ return new RemotePlatformClient({
3054
+ loadConfig: () => loadConfig8(getConfigPath3()),
3055
+ getDataDir: getDataDir4,
3056
+ getPackageVersion,
3057
+ resolvePlatformBase: (rawApiBase) => resolvePlatformApiBase({
3058
+ explicitApiBase: rawApiBase,
3059
+ requireConfigured: true
3060
+ }).platformBase,
3061
+ readManagedServiceState: () => {
3062
+ const state = readServiceState();
3063
+ if (!state) {
3064
+ return null;
3065
+ }
3066
+ return {
3067
+ pid: state.pid,
3068
+ uiPort: state.uiPort
3069
+ };
3070
+ },
3071
+ isProcessRunning
3072
+ });
3197
3073
  }
3198
- function delay(ms, signal) {
3199
- return new Promise((resolveDelay, rejectDelay) => {
3200
- const timer = setTimeout(() => {
3201
- signal?.removeEventListener("abort", onAbort);
3202
- resolveDelay();
3203
- }, ms);
3204
- const onAbort = () => {
3205
- clearTimeout(timer);
3206
- rejectDelay(new Error("Remote connector aborted."));
3207
- };
3208
- if (signal) {
3209
- signal.addEventListener("abort", onAbort, { once: true });
3210
- }
3074
+ function createNextclawRemoteConnector(params = {}) {
3075
+ return new RemoteConnector({
3076
+ platformClient: createNextclawRemotePlatformClient(),
3077
+ logger: params.logger
3211
3078
  });
3212
3079
  }
3213
- function redactWsUrl(url) {
3214
- try {
3215
- const parsed = new URL(url);
3216
- const token = parsed.searchParams.get("token");
3217
- if (token) {
3218
- parsed.searchParams.set("token", maskToken(token));
3080
+ function createNextclawRemoteStatusStore(mode) {
3081
+ return new RemoteStatusStore(mode, {
3082
+ writeRemoteState: (next) => {
3083
+ updateServiceState((state) => ({
3084
+ ...state,
3085
+ remote: next
3086
+ }));
3219
3087
  }
3220
- return parsed.toString();
3221
- } catch {
3222
- return url;
3223
- }
3088
+ });
3224
3089
  }
3225
- var RemotePlatformClient = class {
3226
- remoteDir = join4(getDataDir4(), "remote");
3227
- devicePath = join4(this.remoteDir, "device.json");
3228
- resolveRunContext(opts) {
3229
- const { platformBase, token, config: config2 } = this.resolvePlatformAccess(opts);
3230
- return {
3231
- config: config2,
3232
- platformBase,
3233
- token,
3234
- localOrigin: this.resolveLocalOrigin(config2, opts),
3235
- displayName: this.resolveDisplayName(config2, opts),
3236
- deviceInstallId: this.ensureDeviceInstallId(),
3237
- autoReconnect: opts.once ? false : opts.autoReconnect ?? config2.remote.autoReconnect
3238
- };
3239
- }
3240
- async registerDevice(params) {
3241
- const response = await fetch(`${params.platformBase}/platform/remote/devices/register`, {
3242
- method: "POST",
3243
- headers: {
3244
- "content-type": "application/json",
3245
- authorization: `Bearer ${params.token}`
3246
- },
3247
- body: JSON.stringify({
3248
- deviceInstallId: params.deviceInstallId,
3249
- displayName: params.displayName,
3250
- platform: readPlatform(),
3251
- appVersion: getPackageVersion(),
3252
- localOrigin: params.localOrigin
3253
- })
3254
- });
3255
- const payload = await response.json();
3256
- if (!response.ok || !payload.ok || !payload.data?.device) {
3257
- throw new Error(payload.error?.message ?? `Failed to register remote device (${response.status}).`);
3258
- }
3259
- return payload.data.device;
3260
- }
3261
- ensureDeviceInstallId() {
3262
- const existing = readJsonFile2(this.devicePath);
3263
- if (existing?.deviceInstallId?.trim()) {
3264
- return existing.deviceInstallId.trim();
3265
- }
3266
- const deviceInstallId = crypto.randomUUID();
3267
- ensureDir(this.remoteDir);
3268
- writeJsonFile(this.devicePath, { deviceInstallId });
3269
- return deviceInstallId;
3270
- }
3271
- resolvePlatformAccess(opts) {
3272
- const config2 = loadConfig8(getConfigPath3());
3273
- const providers = config2.providers;
3274
- const nextclawProvider = providers.nextclaw;
3275
- const token = typeof nextclawProvider?.apiKey === "string" ? nextclawProvider.apiKey.trim() : "";
3276
- if (!token) {
3277
- throw new Error('NextClaw platform token is missing. Run "nextclaw login" first.');
3278
- }
3279
- const configuredApiBase = normalizeOptionalString3(config2.remote.platformApiBase) ?? (typeof nextclawProvider?.apiBase === "string" ? nextclawProvider.apiBase.trim() : "");
3280
- const rawApiBase = normalizeOptionalString3(opts.apiBase) ?? configuredApiBase;
3281
- if (!rawApiBase) {
3282
- throw new Error("Platform API base is missing. Pass --api-base, run nextclaw login, or set remote.platformApiBase.");
3283
- }
3284
- const { platformBase } = resolvePlatformApiBase({
3285
- explicitApiBase: rawApiBase,
3286
- requireConfigured: true
3287
- });
3288
- return { platformBase, token, config: config2 };
3289
- }
3290
- resolveLocalOrigin(config2, opts) {
3291
- const explicitOrigin = normalizeOptionalString3(opts.localOrigin);
3292
- if (explicitOrigin) {
3293
- return explicitOrigin.replace(/\/$/, "");
3294
- }
3295
- const state = readServiceState();
3296
- if (state && isProcessRunning(state.pid) && Number.isFinite(state.uiPort)) {
3297
- return `http://127.0.0.1:${state.uiPort}`;
3298
- }
3299
- const configuredPort = typeof config2.ui?.port === "number" && Number.isFinite(config2.ui.port) ? config2.ui.port : 18791;
3300
- return `http://127.0.0.1:${configuredPort}`;
3301
- }
3302
- resolveDisplayName(config2, opts) {
3303
- return normalizeOptionalString3(opts.name) ?? normalizeOptionalString3(config2.remote.deviceName) ?? hostname();
3304
- }
3305
- };
3306
-
3307
- // src/cli/remote/remote-connector.ts
3308
- var RemoteConnector = class {
3309
- constructor(logger = console) {
3310
- this.logger = logger;
3311
- }
3312
- platformClient = new RemotePlatformClient();
3313
- async connectOnce(params) {
3314
- return await new Promise((resolve13, reject) => {
3315
- const socket = new WebSocket(params.wsUrl);
3316
- let settled = false;
3317
- let aborted = false;
3318
- const pingTimer = setInterval(() => {
3319
- if (socket.readyState === WebSocket.OPEN) {
3320
- socket.send(JSON.stringify({ type: "ping", at: (/* @__PURE__ */ new Date()).toISOString() }));
3321
- }
3322
- }, 15e3);
3323
- const cleanup = () => {
3324
- clearInterval(pingTimer);
3325
- params.signal?.removeEventListener("abort", onAbort);
3326
- };
3327
- const finishResolve = (value) => {
3328
- if (settled) {
3329
- return;
3330
- }
3331
- settled = true;
3332
- cleanup();
3333
- resolve13(value);
3334
- };
3335
- const finishReject = (error) => {
3336
- if (settled) {
3337
- return;
3338
- }
3339
- settled = true;
3340
- cleanup();
3341
- reject(error);
3342
- };
3343
- const onAbort = () => {
3344
- aborted = true;
3345
- try {
3346
- socket.close(1e3, "Remote connector aborted");
3347
- } catch {
3348
- finishResolve("aborted");
3349
- }
3350
- };
3351
- if (params.signal) {
3352
- if (params.signal.aborted) {
3353
- onAbort();
3354
- } else {
3355
- params.signal.addEventListener("abort", onAbort, { once: true });
3356
- }
3357
- }
3358
- socket.addEventListener("open", () => {
3359
- params.statusStore?.write({
3360
- enabled: true,
3361
- state: "connected",
3362
- deviceId: params.deviceId,
3363
- deviceName: params.displayName,
3364
- platformBase: params.platformBase,
3365
- localOrigin: params.localOrigin,
3366
- lastConnectedAt: (/* @__PURE__ */ new Date()).toISOString(),
3367
- lastError: null
3368
- });
3369
- this.logger.info(`\u2713 Remote connector connected: ${redactWsUrl(params.wsUrl)}`);
3370
- });
3371
- socket.addEventListener("message", (event) => {
3372
- this.handleSocketMessage({ data: event.data, relayBridge: params.relayBridge, socket });
3373
- });
3374
- socket.addEventListener("close", () => {
3375
- finishResolve(aborted ? "aborted" : "closed");
3376
- });
3377
- socket.addEventListener("error", () => {
3378
- if (aborted) {
3379
- finishResolve("aborted");
3380
- return;
3381
- }
3382
- finishReject(new Error("Remote connector websocket failed."));
3383
- });
3384
- });
3385
- }
3386
- handleSocketMessage(params) {
3387
- void (async () => {
3388
- const frame = this.parseRelayFrame(params.data);
3389
- if (!frame) {
3390
- return;
3391
- }
3392
- try {
3393
- await params.relayBridge.forward(frame, params.socket);
3394
- } catch (error) {
3395
- params.socket.send(JSON.stringify({
3396
- type: "response.error",
3397
- requestId: frame.requestId,
3398
- message: error instanceof Error ? error.message : String(error)
3399
- }));
3400
- }
3401
- })();
3402
- }
3403
- parseRelayFrame(data) {
3404
- try {
3405
- const frame = JSON.parse(String(data ?? ""));
3406
- return frame.type === "request" ? frame : null;
3407
- } catch {
3408
- return null;
3409
- }
3410
- }
3411
- async ensureDevice(params) {
3412
- if (params.device) {
3413
- return params.device;
3414
- }
3415
- const device = await this.platformClient.registerDevice({
3416
- platformBase: params.context.platformBase,
3417
- token: params.context.token,
3418
- deviceInstallId: params.context.deviceInstallId,
3419
- displayName: params.context.displayName,
3420
- localOrigin: params.context.localOrigin
3421
- });
3422
- this.logger.info(`\u2713 Remote device registered: ${device.displayName} (${device.id})`);
3423
- this.logger.info(`\u2713 Local origin: ${params.context.localOrigin}`);
3424
- this.logger.info(`\u2713 Platform: ${params.context.platformBase}`);
3425
- return device;
3426
- }
3427
- writeRemoteState(statusStore, next) {
3428
- statusStore?.write(next);
3429
- }
3430
- async runCycle(params) {
3431
- try {
3432
- this.writeRemoteState(params.opts.statusStore, {
3433
- enabled: true,
3434
- state: "connecting",
3435
- deviceId: params.device?.id,
3436
- deviceName: params.context.displayName,
3437
- platformBase: params.context.platformBase,
3438
- localOrigin: params.context.localOrigin,
3439
- lastError: null
3440
- });
3441
- const device = await this.ensureDevice({ device: params.device, context: params.context });
3442
- const wsUrl = `${params.context.platformBase.replace(/^http/i, "ws")}/platform/remote/connect?deviceId=${encodeURIComponent(device.id)}&token=${encodeURIComponent(params.context.token)}`;
3443
- const outcome = await this.connectOnce({
3444
- wsUrl,
3445
- relayBridge: params.relayBridge,
3446
- signal: params.opts.signal,
3447
- statusStore: params.opts.statusStore,
3448
- displayName: params.context.displayName,
3449
- deviceId: device.id,
3450
- platformBase: params.context.platformBase,
3451
- localOrigin: params.context.localOrigin
3452
- });
3453
- if (outcome !== "aborted") {
3454
- this.writeRemoteState(params.opts.statusStore, {
3455
- enabled: true,
3456
- state: "disconnected",
3457
- deviceId: device.id,
3458
- deviceName: params.context.displayName,
3459
- platformBase: params.context.platformBase,
3460
- localOrigin: params.context.localOrigin,
3461
- lastError: null
3462
- });
3463
- }
3464
- return { device, aborted: outcome === "aborted" };
3465
- } catch (error) {
3466
- const message = error instanceof Error ? error.message : String(error);
3467
- this.writeRemoteState(params.opts.statusStore, {
3468
- enabled: true,
3469
- state: "error",
3470
- deviceId: params.device?.id,
3471
- deviceName: params.context.displayName,
3472
- platformBase: params.context.platformBase,
3473
- localOrigin: params.context.localOrigin,
3474
- lastError: message
3475
- });
3476
- this.logger.error(`Remote connector error: ${message}`);
3477
- return { device: params.device, aborted: false };
3478
- }
3479
- }
3480
- async run(opts = {}) {
3481
- const context = this.platformClient.resolveRunContext(opts);
3482
- const relayBridge = new RemoteRelayBridge(context.localOrigin);
3483
- await relayBridge.ensureLocalUiHealthy();
3484
- let device = null;
3485
- while (!opts.signal?.aborted) {
3486
- const cycle = await this.runCycle({ device, context, relayBridge, opts });
3487
- device = cycle.device;
3488
- if (cycle.aborted || !context.autoReconnect || opts.signal?.aborted) {
3489
- break;
3490
- }
3491
- this.logger.warn("Remote connector disconnected. Reconnecting in 3s...");
3492
- try {
3493
- await delay(3e3, opts.signal);
3494
- } catch {
3495
- break;
3496
- }
3497
- }
3498
- this.writeRemoteState(opts.statusStore, {
3499
- enabled: opts.mode === "service" ? true : Boolean(context.config.remote.enabled),
3500
- state: opts.signal?.aborted ? "disconnected" : "disabled",
3501
- deviceId: device?.id,
3502
- deviceName: context.displayName,
3503
- platformBase: context.platformBase,
3504
- localOrigin: context.localOrigin,
3505
- lastError: null
3506
- });
3507
- }
3508
- };
3509
-
3510
- // src/cli/remote/remote-status-store.ts
3511
- import { hostname as hostname2 } from "os";
3512
- import { loadConfig as loadConfig9 } from "@nextclaw/core";
3513
- function normalizeOptionalString4(value) {
3514
- if (typeof value !== "string") {
3515
- return void 0;
3516
- }
3517
- const trimmed = value.trim();
3518
- return trimmed.length > 0 ? trimmed : void 0;
3090
+ function buildNextclawConfiguredRemoteState(config2) {
3091
+ return buildConfiguredRemoteState(config2);
3519
3092
  }
3520
- function buildConfiguredRemoteState(config2 = loadConfig9()) {
3521
- const remote = config2.remote;
3522
- return {
3523
- enabled: Boolean(remote.enabled),
3524
- mode: "service",
3525
- state: remote.enabled ? "disconnected" : "disabled",
3526
- ...normalizeOptionalString4(remote.deviceName) ? { deviceName: normalizeOptionalString4(remote.deviceName) } : {},
3527
- ...normalizeOptionalString4(remote.platformApiBase) ? { platformBase: normalizeOptionalString4(remote.platformApiBase) } : {},
3528
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3529
- };
3093
+ function readCurrentNextclawRemoteRuntimeState() {
3094
+ return readServiceState()?.remote ?? null;
3530
3095
  }
3531
- function resolveRemoteStatusSnapshot(config2 = loadConfig9()) {
3532
- const serviceState = readServiceState();
3533
- if (serviceState?.remote) {
3534
- return {
3535
- configuredEnabled: Boolean(config2.remote.enabled),
3536
- runtime: serviceState.remote
3537
- };
3538
- }
3539
- if (config2.remote.enabled) {
3540
- return {
3541
- configuredEnabled: true,
3542
- runtime: {
3543
- ...buildConfiguredRemoteState(config2),
3544
- deviceName: normalizeOptionalString4(config2.remote.deviceName) ?? hostname2()
3545
- }
3546
- };
3547
- }
3548
- return {
3549
- configuredEnabled: false,
3550
- runtime: null
3551
- };
3096
+ function resolveNextclawRemoteStatusSnapshot(config2) {
3097
+ return resolveRemoteStatusSnapshot({
3098
+ config: config2,
3099
+ currentRemoteState: readCurrentNextclawRemoteRuntimeState()
3100
+ });
3552
3101
  }
3553
- var RemoteStatusStore = class {
3554
- constructor(mode) {
3555
- this.mode = mode;
3556
- }
3557
- write(next) {
3558
- updateServiceState((state) => ({
3559
- ...state,
3560
- remote: {
3561
- ...state.remote,
3562
- ...next,
3563
- mode: this.mode,
3564
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3565
- }
3566
- }));
3567
- }
3568
- };
3569
3102
 
3570
3103
  // src/cli/commands/remote.ts
3571
- function normalizeOptionalString5(value) {
3104
+ function normalizeOptionalString3(value) {
3572
3105
  if (typeof value !== "string") {
3573
3106
  return void 0;
3574
3107
  }
@@ -3599,14 +3132,14 @@ async function probeLocalUi(localOrigin) {
3599
3132
  }
3600
3133
  var RemoteCommands = class {
3601
3134
  enableConfig(opts = {}) {
3602
- const config2 = loadConfig10(getConfigPath4());
3135
+ const config2 = loadConfig9(getConfigPath4());
3603
3136
  const next = {
3604
3137
  ...config2,
3605
3138
  remote: {
3606
3139
  ...config2.remote,
3607
3140
  enabled: true,
3608
- ...normalizeOptionalString5(opts.apiBase) ? { platformApiBase: normalizeOptionalString5(opts.apiBase) ?? "" } : {},
3609
- ...normalizeOptionalString5(opts.name) ? { deviceName: normalizeOptionalString5(opts.name) ?? "" } : {}
3141
+ ...normalizeOptionalString3(opts.apiBase) ? { platformApiBase: normalizeOptionalString3(opts.apiBase) ?? "" } : {},
3142
+ ...normalizeOptionalString3(opts.name) ? { deviceName: normalizeOptionalString3(opts.name) ?? "" } : {}
3610
3143
  }
3611
3144
  };
3612
3145
  saveConfig7(next);
@@ -3616,7 +3149,7 @@ var RemoteCommands = class {
3616
3149
  };
3617
3150
  }
3618
3151
  disableConfig() {
3619
- const config2 = loadConfig10(getConfigPath4());
3152
+ const config2 = loadConfig9(getConfigPath4());
3620
3153
  const next = {
3621
3154
  ...config2,
3622
3155
  remote: {
@@ -3631,15 +3164,15 @@ var RemoteCommands = class {
3631
3164
  };
3632
3165
  }
3633
3166
  async connect(opts = {}) {
3634
- const connector = new RemoteConnector();
3167
+ const connector = createNextclawRemoteConnector();
3635
3168
  await connector.run({
3636
3169
  ...opts,
3637
3170
  mode: "foreground"
3638
3171
  });
3639
3172
  }
3640
3173
  async status(opts = {}) {
3641
- const config2 = loadConfig10(getConfigPath4());
3642
- const snapshot = resolveRemoteStatusSnapshot(config2);
3174
+ const config2 = loadConfig9(getConfigPath4());
3175
+ const snapshot = resolveNextclawRemoteStatusSnapshot(config2);
3643
3176
  if (opts.json) {
3644
3177
  console.log(JSON.stringify(snapshot, null, 2));
3645
3178
  return;
@@ -3649,9 +3182,9 @@ var RemoteCommands = class {
3649
3182
  console.log(`Enabled: ${snapshot.configuredEnabled ? "yes" : "no"}`);
3650
3183
  console.log(`Mode: ${runtime2?.mode ?? "service"}`);
3651
3184
  console.log(`State: ${runtime2?.state ?? "disabled"}`);
3652
- console.log(`Device: ${runtime2?.deviceName ?? normalizeOptionalString5(config2.remote.deviceName) ?? hostname3()}`);
3185
+ console.log(`Device: ${runtime2?.deviceName ?? normalizeOptionalString3(config2.remote.deviceName) ?? hostname()}`);
3653
3186
  console.log(
3654
- `Platform: ${runtime2?.platformBase ?? normalizeOptionalString5(config2.remote.platformApiBase) ?? normalizeOptionalString5(config2.providers.nextclaw?.apiBase) ?? "not set"}`
3187
+ `Platform: ${runtime2?.platformBase ?? normalizeOptionalString3(config2.remote.platformApiBase) ?? normalizeOptionalString3(config2.providers.nextclaw?.apiBase) ?? "not set"}`
3655
3188
  );
3656
3189
  console.log(`Local origin: ${runtime2?.localOrigin ?? resolveConfiguredLocalOrigin(config2)}`);
3657
3190
  if (runtime2?.deviceId) {
@@ -3665,12 +3198,12 @@ var RemoteCommands = class {
3665
3198
  }
3666
3199
  }
3667
3200
  async doctor(opts = {}) {
3668
- const config2 = loadConfig10(getConfigPath4());
3669
- const snapshot = resolveRemoteStatusSnapshot(config2);
3201
+ const config2 = loadConfig9(getConfigPath4());
3202
+ const snapshot = resolveNextclawRemoteStatusSnapshot(config2);
3670
3203
  const localOrigin = resolveConfiguredLocalOrigin(config2);
3671
3204
  const localUi = await probeLocalUi(localOrigin);
3672
- const token = normalizeOptionalString5(config2.providers.nextclaw?.apiKey);
3673
- const platformApiBase = normalizeOptionalString5(config2.remote.platformApiBase) ?? normalizeOptionalString5(config2.providers.nextclaw?.apiBase);
3205
+ const token = normalizeOptionalString3(config2.providers.nextclaw?.apiKey);
3206
+ const platformApiBase = normalizeOptionalString3(config2.remote.platformApiBase) ?? normalizeOptionalString3(config2.providers.nextclaw?.apiBase);
3674
3207
  const checks = [
3675
3208
  {
3676
3209
  name: "remote-enabled",
@@ -3711,7 +3244,7 @@ var RemoteCommands = class {
3711
3244
 
3712
3245
  // src/cli/commands/diagnostics.ts
3713
3246
  import { createServer as createNetServer } from "net";
3714
- import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
3247
+ import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
3715
3248
  import { resolve as resolve8 } from "path";
3716
3249
  import {
3717
3250
  APP_NAME as APP_NAME2,
@@ -3719,7 +3252,7 @@ import {
3719
3252
  getDataDir as getDataDir5,
3720
3253
  getWorkspacePath as getWorkspacePath4,
3721
3254
  hasSecretRef,
3722
- loadConfig as loadConfig11
3255
+ loadConfig as loadConfig10
3723
3256
  } from "@nextclaw/core";
3724
3257
  import { listBuiltinProviders } from "@nextclaw/runtime";
3725
3258
 
@@ -3905,7 +3438,7 @@ var DiagnosticsCommands = class {
3905
3438
  }
3906
3439
  async collectRuntimeStatus(params) {
3907
3440
  const configPath = getConfigPath5();
3908
- const config2 = loadConfig11();
3441
+ const config2 = loadConfig10();
3909
3442
  const workspacePath = getWorkspacePath4(config2.agents.defaults.workspace);
3910
3443
  const serviceStatePath = resolve8(getDataDir5(), "run", "service.json");
3911
3444
  const fixActions = [];
@@ -3925,7 +3458,7 @@ var DiagnosticsCommands = class {
3925
3458
  const managedApiUrl = serviceState?.apiUrl ?? null;
3926
3459
  const managedHealth = running && managedApiUrl ? await this.probeApiHealth(`${managedApiUrl}/health`) : { state: "unreachable", detail: "service not running" };
3927
3460
  const configuredHealth = await this.probeApiHealth(`${configuredApiUrl}/health`, 900);
3928
- const remote = resolveRemoteStatusSnapshot(config2);
3461
+ const remote = resolveNextclawRemoteStatusSnapshot(config2);
3929
3462
  const orphanSuspected = !running && configuredHealth.state === "ok";
3930
3463
  const providers = this.listProviderStatuses(config2);
3931
3464
  const issues = [];
@@ -3948,13 +3481,13 @@ var DiagnosticsCommands = class {
3948
3481
  return {
3949
3482
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3950
3483
  configPath,
3951
- configExists: existsSync7(configPath),
3484
+ configExists: existsSync6(configPath),
3952
3485
  workspacePath,
3953
- workspaceExists: existsSync7(workspacePath),
3486
+ workspaceExists: existsSync6(workspacePath),
3954
3487
  model: config2.agents.defaults.model,
3955
3488
  providers,
3956
3489
  serviceStatePath,
3957
- serviceStateExists: existsSync7(serviceStatePath),
3490
+ serviceStateExists: existsSync6(serviceStatePath),
3958
3491
  fixActions,
3959
3492
  process: {
3960
3493
  managedByState,
@@ -4026,11 +3559,11 @@ var DiagnosticsCommands = class {
4026
3559
  });
4027
3560
  }
4028
3561
  collectRuntimeIssues(params) {
4029
- if (!existsSync7(params.configPath)) {
3562
+ if (!existsSync6(params.configPath)) {
4030
3563
  params.issues.push("Config file is missing.");
4031
3564
  params.recommendations.push(`Run ${APP_NAME2} init to create config files.`);
4032
3565
  }
4033
- if (!existsSync7(params.workspacePath)) {
3566
+ if (!existsSync6(params.workspacePath)) {
4034
3567
  params.issues.push("Workspace directory does not exist.");
4035
3568
  params.recommendations.push(`Run ${APP_NAME2} init to create workspace templates.`);
4036
3569
  }
@@ -4059,11 +3592,11 @@ var DiagnosticsCommands = class {
4059
3592
  }
4060
3593
  }
4061
3594
  readLogTail(path2, maxLines = 25) {
4062
- if (!existsSync7(path2)) {
3595
+ if (!existsSync6(path2)) {
4063
3596
  return [];
4064
3597
  }
4065
3598
  try {
4066
- const lines = readFileSync7(path2, "utf-8").split(/\r?\n/).filter(Boolean);
3599
+ const lines = readFileSync6(path2, "utf-8").split(/\r?\n/).filter(Boolean);
4067
3600
  if (lines.length <= maxLines) {
4068
3601
  return lines;
4069
3602
  }
@@ -4103,8 +3636,8 @@ import {
4103
3636
  stopPluginChannelGateways as stopPluginChannelGateways2
4104
3637
  } from "@nextclaw/openclaw-compat";
4105
3638
  import { startUiServer } from "@nextclaw/server";
4106
- import { appendFileSync, closeSync, cpSync as cpSync2, existsSync as existsSync11, mkdirSync as mkdirSync6, openSync } from "fs";
4107
- import { dirname as dirname3, join as join7, resolve as resolve10 } from "path";
3639
+ import { appendFileSync, closeSync, cpSync as cpSync2, existsSync as existsSync10, mkdirSync as mkdirSync5, openSync } from "fs";
3640
+ import { dirname as dirname2, join as join6, resolve as resolve10 } from "path";
4108
3641
  import { spawn as spawn2 } from "child_process";
4109
3642
  import { request as httpRequest } from "http";
4110
3643
  import { request as httpsRequest } from "https";
@@ -4113,7 +3646,7 @@ import chokidar from "chokidar";
4113
3646
 
4114
3647
  // src/cli/gateway/controller.ts
4115
3648
  import { createHash } from "crypto";
4116
- import { existsSync as existsSync8, readFileSync as readFileSync8 } from "fs";
3649
+ import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
4117
3650
  import {
4118
3651
  buildConfigSchema,
4119
3652
  ConfigSchema,
@@ -4125,8 +3658,8 @@ var readConfigSnapshot = (getConfigPath8) => {
4125
3658
  const path2 = getConfigPath8();
4126
3659
  let raw = "";
4127
3660
  let parsed = {};
4128
- if (existsSync8(path2)) {
4129
- raw = readFileSync8(path2, "utf-8");
3661
+ if (existsSync7(path2)) {
3662
+ raw = readFileSync7(path2, "utf-8");
4130
3663
  try {
4131
3664
  parsed = JSON.parse(raw);
4132
3665
  } catch {
@@ -4233,11 +3766,11 @@ var GatewayControllerImpl = class {
4233
3766
  await this.deps.requestRestart(options);
4234
3767
  return;
4235
3768
  }
4236
- const delay2 = typeof options?.delayMs === "number" && Number.isFinite(options.delayMs) ? Math.max(0, options.delayMs) : 100;
3769
+ const delay = typeof options?.delayMs === "number" && Number.isFinite(options.delayMs) ? Math.max(0, options.delayMs) : 100;
4237
3770
  console.log(`Gateway restart requested via tool${options?.reason ? ` (${options.reason})` : ""}.`);
4238
3771
  setTimeout(() => {
4239
3772
  process.exit(0);
4240
- }, delay2);
3773
+ }, delay);
4241
3774
  }
4242
3775
  status() {
4243
3776
  return {
@@ -4583,9 +4116,9 @@ var MissingProvider = class extends LLMProvider {
4583
4116
  };
4584
4117
 
4585
4118
  // src/cli/commands/service-marketplace-installer.ts
4586
- import { getWorkspacePath as getWorkspacePath5, loadConfig as loadConfig13 } from "@nextclaw/core";
4587
- import { existsSync as existsSync9, rmSync as rmSync4 } from "fs";
4588
- import { join as join5 } from "path";
4119
+ import { getWorkspacePath as getWorkspacePath5, loadConfig as loadConfig12 } from "@nextclaw/core";
4120
+ import { existsSync as existsSync8, rmSync as rmSync4 } from "fs";
4121
+ import { join as join4 } from "path";
4589
4122
 
4590
4123
  // src/cli/commands/service-marketplace-helpers.ts
4591
4124
  var containsAbsoluteFsPath = (line) => {
@@ -4633,7 +4166,7 @@ var buildMarketplaceSkillInstallArgs = (params) => {
4633
4166
  };
4634
4167
 
4635
4168
  // src/cli/commands/service-mcp-marketplace-ops.ts
4636
- import { loadConfig as loadConfig12, saveConfig as saveConfig8 } from "@nextclaw/core";
4169
+ import { loadConfig as loadConfig11, saveConfig as saveConfig8 } from "@nextclaw/core";
4637
4170
  import { McpDoctorFacade as McpDoctorFacade2, McpMutationService as McpMutationService2 } from "@nextclaw/mcp";
4638
4171
  var ServiceMcpMarketplaceOps = class {
4639
4172
  constructor(options) {
@@ -4701,13 +4234,13 @@ var ServiceMcpMarketplaceOps = class {
4701
4234
  }
4702
4235
  createMutationService() {
4703
4236
  return new McpMutationService2({
4704
- getConfig: () => loadConfig12(),
4237
+ getConfig: () => loadConfig11(),
4705
4238
  saveConfig: (config2) => saveConfig8(config2)
4706
4239
  });
4707
4240
  }
4708
4241
  createDoctorFacade() {
4709
4242
  return new McpDoctorFacade2({
4710
- getConfig: () => loadConfig12()
4243
+ getConfig: () => loadConfig11()
4711
4244
  });
4712
4245
  }
4713
4246
  };
@@ -4748,7 +4281,7 @@ var ServiceMarketplaceInstaller = class {
4748
4281
  if (params.kind && params.kind !== "marketplace") {
4749
4282
  throw new Error(`Unsupported marketplace skill kind: ${params.kind}`);
4750
4283
  }
4751
- const workspace = getWorkspacePath5(loadConfig13().agents.defaults.workspace);
4284
+ const workspace = getWorkspacePath5(loadConfig12().agents.defaults.workspace);
4752
4285
  const args = buildMarketplaceSkillInstallArgs({
4753
4286
  slug: params.slug,
4754
4287
  workspace,
@@ -4787,9 +4320,9 @@ var ServiceMarketplaceInstaller = class {
4787
4320
  return { message: result.message };
4788
4321
  }
4789
4322
  async uninstallSkill(slug) {
4790
- const workspace = getWorkspacePath5(loadConfig13().agents.defaults.workspace);
4791
- const targetDir = join5(workspace, "skills", slug);
4792
- if (!existsSync9(targetDir)) {
4323
+ const workspace = getWorkspacePath5(loadConfig12().agents.defaults.workspace);
4324
+ const targetDir = join4(workspace, "skills", slug);
4325
+ if (!existsSync8(targetDir)) {
4793
4326
  throw new Error(`Skill not installed in workspace: ${slug}`);
4794
4327
  }
4795
4328
  rmSync4(targetDir, { recursive: true, force: true });
@@ -5922,7 +5455,7 @@ function resolveRequestedToolNames(metadata) {
5922
5455
  )
5923
5456
  );
5924
5457
  }
5925
- function normalizeOptionalString6(value) {
5458
+ function normalizeOptionalString4(value) {
5926
5459
  return normalizeString(value) ?? void 0;
5927
5460
  }
5928
5461
  function readMetadataModel(metadata) {
@@ -6042,7 +5575,7 @@ var NextclawNcpContextBuilder = class {
6042
5575
  if (inboundModel) {
6043
5576
  session.metadata.preferred_model = inboundModel;
6044
5577
  }
6045
- const effectiveModel = normalizeOptionalString6(session.metadata.preferred_model) ?? profile.model;
5578
+ const effectiveModel = normalizeOptionalString4(session.metadata.preferred_model) ?? profile.model;
6046
5579
  const clearThinking = requestMetadata.clear_thinking === true || requestMetadata.reset_thinking === true;
6047
5580
  if (clearThinking) {
6048
5581
  delete session.metadata.preferred_thinking;
@@ -6059,8 +5592,8 @@ var NextclawNcpContextBuilder = class {
6059
5592
  model: effectiveModel,
6060
5593
  sessionThinkingLevel: parseThinkingLevel(session.metadata.preferred_thinking) ?? null
6061
5594
  });
6062
- const channel = normalizeOptionalString6(requestMetadata.channel) ?? normalizeOptionalString6(session.metadata.last_channel) ?? "ui";
6063
- const chatId = normalizeOptionalString6(requestMetadata.chatId) ?? normalizeOptionalString6(requestMetadata.chat_id) ?? normalizeOptionalString6(session.metadata.last_to) ?? "web-ui";
5595
+ const channel = normalizeOptionalString4(requestMetadata.channel) ?? normalizeOptionalString4(session.metadata.last_channel) ?? "ui";
5596
+ const chatId = normalizeOptionalString4(requestMetadata.chatId) ?? normalizeOptionalString4(requestMetadata.chat_id) ?? normalizeOptionalString4(session.metadata.last_to) ?? "web-ui";
6064
5597
  session.metadata.last_channel = channel;
6065
5598
  session.metadata.last_to = chatId;
6066
5599
  const requestedSkillNames = resolveRequestedSkillNames(requestMetadata);
@@ -6778,70 +6311,8 @@ async function createUiNcpAgent(params) {
6778
6311
  };
6779
6312
  }
6780
6313
 
6781
- // src/cli/remote/remote-service-module.ts
6782
- var RemoteServiceModule = class {
6783
- constructor(deps) {
6784
- this.deps = deps;
6785
- }
6786
- abortController = null;
6787
- runTask = null;
6788
- statusStore = new RemoteStatusStore("service");
6789
- start() {
6790
- if (!this.deps.config.remote.enabled) {
6791
- this.statusStore.write({
6792
- enabled: false,
6793
- state: "disabled",
6794
- deviceName: void 0,
6795
- deviceId: void 0,
6796
- platformBase: void 0,
6797
- localOrigin: this.deps.localOrigin,
6798
- lastError: null,
6799
- lastConnectedAt: null
6800
- });
6801
- return null;
6802
- }
6803
- const logger = this.deps.logger ?? {
6804
- info: (message) => console.log(`[remote] ${message}`),
6805
- warn: (message) => console.warn(`[remote] ${message}`),
6806
- error: (message) => console.error(`[remote] ${message}`)
6807
- };
6808
- this.abortController = new AbortController();
6809
- const connector = new RemoteConnector(logger);
6810
- this.runTask = connector.run({
6811
- mode: "service",
6812
- signal: this.abortController.signal,
6813
- autoReconnect: this.deps.config.remote.autoReconnect,
6814
- localOrigin: this.deps.localOrigin,
6815
- statusStore: this.statusStore
6816
- });
6817
- void this.runTask.catch((error) => {
6818
- const message = error instanceof Error ? error.message : String(error);
6819
- this.statusStore.write({
6820
- enabled: true,
6821
- state: "error",
6822
- deviceName: this.deps.config.remote.deviceName || void 0,
6823
- deviceId: void 0,
6824
- platformBase: this.deps.config.remote.platformApiBase || void 0,
6825
- localOrigin: this.deps.localOrigin,
6826
- lastError: message
6827
- });
6828
- logger.error(message);
6829
- });
6830
- return this.runTask;
6831
- }
6832
- async stop() {
6833
- this.abortController?.abort();
6834
- try {
6835
- await this.runTask;
6836
- } catch {
6837
- } finally {
6838
- this.abortController = null;
6839
- this.runTask = null;
6840
- }
6841
- }
6842
- };
6843
-
6844
6314
  // src/cli/commands/service-remote-runtime.ts
6315
+ import { RemoteServiceModule } from "@nextclaw/remote";
6845
6316
  function createManagedRemoteModule(params) {
6846
6317
  if (!params.config.ui.enabled) {
6847
6318
  return null;
@@ -6849,6 +6320,8 @@ function createManagedRemoteModule(params) {
6849
6320
  return new RemoteServiceModule({
6850
6321
  config: params.config,
6851
6322
  localOrigin: params.localOrigin,
6323
+ statusStore: createNextclawRemoteStatusStore("service"),
6324
+ createConnector: (logger) => createNextclawRemoteConnector({ logger }),
6852
6325
  logger: {
6853
6326
  info: (message) => console.log(`[remote] ${message}`),
6854
6327
  warn: (message) => console.warn(`[remote] ${message}`),
@@ -6868,7 +6341,7 @@ function writeInitialManagedServiceState(params) {
6868
6341
  startupLastProbeError: null,
6869
6342
  startupTimeoutMs: params.readinessTimeoutMs,
6870
6343
  startupCheckedAt: (/* @__PURE__ */ new Date()).toISOString(),
6871
- ...params.config.remote.enabled ? { remote: buildConfiguredRemoteState(params.config) } : {}
6344
+ ...params.config.remote.enabled ? { remote: buildNextclawConfiguredRemoteState(params.config) } : {}
6872
6345
  });
6873
6346
  }
6874
6347
  function writeReadyManagedServiceState(params) {
@@ -6892,14 +6365,14 @@ function writeReadyManagedServiceState(params) {
6892
6365
  }
6893
6366
 
6894
6367
  // src/cli/commands/ui-chat-run-coordinator.ts
6895
- import { existsSync as existsSync10, mkdirSync as mkdirSync5, readdirSync as readdirSync2, readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "fs";
6896
- import { join as join6 } from "path";
6368
+ import { existsSync as existsSync9, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
6369
+ import { join as join5 } from "path";
6897
6370
  import {
6898
6371
  getDataDir as getDataDir6,
6899
6372
  parseAgentScopedSessionKey as parseAgentScopedSessionKey2,
6900
6373
  safeFilename
6901
6374
  } from "@nextclaw/core";
6902
- var RUNS_DIR = join6(getDataDir6(), "runs");
6375
+ var RUNS_DIR = join5(getDataDir6(), "runs");
6903
6376
  var NON_TERMINAL_STATES = /* @__PURE__ */ new Set(["queued", "running"]);
6904
6377
  var DEFAULT_SESSION_TYPE = "native";
6905
6378
  var SESSION_TYPE_METADATA_KEY = "session_type";
@@ -6958,7 +6431,7 @@ function hasToolSessionEvent(run) {
6958
6431
  var UiChatRunCoordinator = class {
6959
6432
  constructor(options) {
6960
6433
  this.options = options;
6961
- mkdirSync5(RUNS_DIR, { recursive: true });
6434
+ mkdirSync4(RUNS_DIR, { recursive: true });
6962
6435
  this.loadPersistedRuns();
6963
6436
  }
6964
6437
  runs = /* @__PURE__ */ new Map();
@@ -7425,7 +6898,7 @@ var UiChatRunCoordinator = class {
7425
6898
  };
7426
6899
  }
7427
6900
  getRunPath(runId) {
7428
- return join6(RUNS_DIR, `${safeFilename(runId)}.json`);
6901
+ return join5(RUNS_DIR, `${safeFilename(runId)}.json`);
7429
6902
  }
7430
6903
  persistRun(run) {
7431
6904
  const persisted = {
@@ -7443,20 +6916,20 @@ var UiChatRunCoordinator = class {
7443
6916
  ...typeof run.reply === "string" ? { reply: run.reply } : {},
7444
6917
  events: run.events
7445
6918
  };
7446
- writeFileSync5(this.getRunPath(run.runId), `${JSON.stringify(persisted, null, 2)}
6919
+ writeFileSync4(this.getRunPath(run.runId), `${JSON.stringify(persisted, null, 2)}
7447
6920
  `);
7448
6921
  }
7449
6922
  loadPersistedRuns() {
7450
- if (!existsSync10(RUNS_DIR)) {
6923
+ if (!existsSync9(RUNS_DIR)) {
7451
6924
  return;
7452
6925
  }
7453
6926
  for (const entry of readdirSync2(RUNS_DIR, { withFileTypes: true })) {
7454
6927
  if (!entry.isFile() || !entry.name.endsWith(".json")) {
7455
6928
  continue;
7456
6929
  }
7457
- const path2 = join6(RUNS_DIR, entry.name);
6930
+ const path2 = join5(RUNS_DIR, entry.name);
7458
6931
  try {
7459
- const parsed = JSON.parse(readFileSync9(path2, "utf-8"));
6932
+ const parsed = JSON.parse(readFileSync8(path2, "utf-8"));
7460
6933
  const runId = readOptionalString(parsed.runId);
7461
6934
  const sessionKey = readOptionalString(parsed.sessionKey);
7462
6935
  if (!runId || !sessionKey) {
@@ -7522,7 +6995,7 @@ var {
7522
6995
  getWorkspacePath: getWorkspacePath9,
7523
6996
  HeartbeatService,
7524
6997
  LiteLLMProvider,
7525
- loadConfig: loadConfig14,
6998
+ loadConfig: loadConfig13,
7526
6999
  MessageBus,
7527
7000
  ProviderManager,
7528
7001
  resolveConfigSecrets: resolveConfigSecrets2,
@@ -7547,7 +7020,7 @@ var ServiceCommands = class {
7547
7020
  this.applyLiveConfigReload = null;
7548
7021
  this.liveUiNcpAgent = null;
7549
7022
  const runtimeConfigPath = getConfigPath6();
7550
- const config2 = resolveConfigSecrets2(loadConfig14(), { configPath: runtimeConfigPath });
7023
+ const config2 = resolveConfigSecrets2(loadConfig13(), { configPath: runtimeConfigPath });
7551
7024
  const workspace = getWorkspacePath9(config2.agents.defaults.workspace);
7552
7025
  let pluginRegistry = loadPluginRegistry(config2, workspace);
7553
7026
  let extensionRegistry = toExtensionRegistry(pluginRegistry);
@@ -7560,7 +7033,7 @@ var ServiceCommands = class {
7560
7033
  });
7561
7034
  const sessionManager = new SessionManager(workspace);
7562
7035
  let pluginGatewayHandles = [];
7563
- const cronStorePath = join7(getDataDir7(), "cron", "jobs.json");
7036
+ const cronStorePath = join6(getDataDir7(), "cron", "jobs.json");
7564
7037
  const cron2 = new CronService2(cronStorePath);
7565
7038
  const uiConfig = resolveUiConfig(config2, options.uiOverrides);
7566
7039
  const uiStaticDir = options.uiStaticDir === void 0 ? resolveUiStaticDir() : options.uiStaticDir;
@@ -7576,7 +7049,7 @@ var ServiceCommands = class {
7576
7049
  sessionManager,
7577
7050
  providerManager,
7578
7051
  makeProvider: (nextConfig) => this.makeProvider(nextConfig, { allowMissing: true }) ?? this.makeMissingProvider(nextConfig),
7579
- loadConfig: () => resolveConfigSecrets2(loadConfig14(), { configPath: runtimeConfigPath }),
7052
+ loadConfig: () => resolveConfigSecrets2(loadConfig13(), { configPath: runtimeConfigPath }),
7580
7053
  getExtensionChannels: () => extensionRegistry.channels,
7581
7054
  onRestartRequired: (paths) => {
7582
7055
  void this.deps.requestRestart({
@@ -7587,7 +7060,7 @@ var ServiceCommands = class {
7587
7060
  }
7588
7061
  });
7589
7062
  this.applyLiveConfigReload = async () => {
7590
- await reloader.applyReloadPlan(resolveConfigSecrets2(loadConfig14(), { configPath: runtimeConfigPath }));
7063
+ await reloader.applyReloadPlan(resolveConfigSecrets2(loadConfig13(), { configPath: runtimeConfigPath }));
7591
7064
  };
7592
7065
  const gatewayController = new GatewayControllerImpl({
7593
7066
  reloader,
@@ -7620,7 +7093,7 @@ var ServiceCommands = class {
7620
7093
  resolveMessageToolHints: ({ channel, accountId }) => resolvePluginChannelMessageToolHints({
7621
7094
  registry: pluginRegistry,
7622
7095
  channel,
7623
- cfg: resolveConfigSecrets2(loadConfig14(), { configPath: runtimeConfigPath }),
7096
+ cfg: resolveConfigSecrets2(loadConfig13(), { configPath: runtimeConfigPath }),
7624
7097
  accountId
7625
7098
  })
7626
7099
  });
@@ -7653,12 +7126,12 @@ var ServiceCommands = class {
7653
7126
  });
7654
7127
  let pluginChannelBindings = getPluginChannelBindings3(pluginRegistry);
7655
7128
  setPluginRuntimeBridge({
7656
- loadConfig: () => toPluginConfigView(resolveConfigSecrets2(loadConfig14(), { configPath: runtimeConfigPath }), pluginChannelBindings),
7129
+ loadConfig: () => toPluginConfigView(resolveConfigSecrets2(loadConfig13(), { configPath: runtimeConfigPath }), pluginChannelBindings),
7657
7130
  writeConfigFile: async (nextConfigView) => {
7658
7131
  if (!nextConfigView || typeof nextConfigView !== "object" || Array.isArray(nextConfigView)) {
7659
7132
  throw new Error("plugin runtime writeConfigFile expects an object config");
7660
7133
  }
7661
- const current = loadConfig14();
7134
+ const current = loadConfig13();
7662
7135
  const next = mergePluginConfigView(current, nextConfigView, pluginChannelBindings);
7663
7136
  saveConfig9(next);
7664
7137
  },
@@ -7734,12 +7207,12 @@ var ServiceCommands = class {
7734
7207
  providerManager,
7735
7208
  bus,
7736
7209
  gatewayController,
7737
- () => resolveConfigSecrets2(loadConfig14(), { configPath: runtimeConfigPath }),
7210
+ () => resolveConfigSecrets2(loadConfig13(), { configPath: runtimeConfigPath }),
7738
7211
  () => extensionRegistry,
7739
7212
  ({ channel, accountId }) => resolvePluginChannelMessageToolHints({
7740
7213
  registry: pluginRegistry,
7741
7214
  channel,
7742
- cfg: resolveConfigSecrets2(loadConfig14(), { configPath: runtimeConfigPath }),
7215
+ cfg: resolveConfigSecrets2(loadConfig13(), { configPath: runtimeConfigPath }),
7743
7216
  accountId
7744
7217
  })
7745
7218
  );
@@ -7898,7 +7371,7 @@ var ServiceCommands = class {
7898
7371
  });
7899
7372
  }
7900
7373
  async runForeground(options) {
7901
- const config2 = loadConfig14();
7374
+ const config2 = loadConfig13();
7902
7375
  const uiConfig = resolveUiConfig(config2, options.uiOverrides);
7903
7376
  const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
7904
7377
  if (options.open) {
@@ -7911,7 +7384,7 @@ var ServiceCommands = class {
7911
7384
  });
7912
7385
  }
7913
7386
  async startService(options) {
7914
- const config2 = loadConfig14();
7387
+ const config2 = loadConfig13();
7915
7388
  const uiConfig = resolveUiConfig(config2, options.uiOverrides);
7916
7389
  const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
7917
7390
  const apiUrl = `${uiUrl}/api`;
@@ -7972,7 +7445,7 @@ var ServiceCommands = class {
7972
7445
  }
7973
7446
  const logPath = resolveServiceLogPath();
7974
7447
  const logDir = resolve10(logPath, "..");
7975
- mkdirSync6(logDir, { recursive: true });
7448
+ mkdirSync5(logDir, { recursive: true });
7976
7449
  const logFd = openSync(logPath, "a");
7977
7450
  const readinessTimeoutMs = this.resolveStartupTimeoutMs(options.startupTimeoutMs);
7978
7451
  const quickPhaseTimeoutMs = Math.min(8e3, readinessTimeoutMs);
@@ -8534,10 +8007,10 @@ var ServiceCommands = class {
8534
8007
  }
8535
8008
  }
8536
8009
  installBuiltinMarketplaceSkill(slug, force) {
8537
- const workspace = getWorkspacePath9(loadConfig14().agents.defaults.workspace);
8538
- const destination = join7(workspace, "skills", slug);
8539
- const destinationSkillFile = join7(destination, "SKILL.md");
8540
- if (existsSync11(destinationSkillFile) && !force) {
8010
+ const workspace = getWorkspacePath9(loadConfig13().agents.defaults.workspace);
8011
+ const destination = join6(workspace, "skills", slug);
8012
+ const destinationSkillFile = join6(destination, "SKILL.md");
8013
+ if (existsSync10(destinationSkillFile) && !force) {
8541
8014
  return {
8542
8015
  message: `${slug} is already installed`
8543
8016
  };
@@ -8545,15 +8018,15 @@ var ServiceCommands = class {
8545
8018
  const loader = createSkillsLoader(workspace);
8546
8019
  const builtin = (loader?.listSkills(false) ?? []).find((skill) => skill.name === slug && skill.source === "builtin");
8547
8020
  if (!builtin) {
8548
- if (existsSync11(destinationSkillFile)) {
8021
+ if (existsSync10(destinationSkillFile)) {
8549
8022
  return {
8550
8023
  message: `${slug} is already installed`
8551
8024
  };
8552
8025
  }
8553
8026
  return null;
8554
8027
  }
8555
- mkdirSync6(join7(workspace, "skills"), { recursive: true });
8556
- cpSync2(dirname3(builtin.path), destination, { recursive: true, force: true });
8028
+ mkdirSync5(join6(workspace, "skills"), { recursive: true });
8029
+ cpSync2(dirname2(builtin.path), destination, { recursive: true, force: true });
8557
8030
  return {
8558
8031
  message: `Installed skill: ${slug}`
8559
8032
  };
@@ -8611,58 +8084,12 @@ ${stderr}`.trim();
8611
8084
  }
8612
8085
  };
8613
8086
 
8614
- // src/cli/remote/remote-runtime-actions.ts
8615
- import { APP_NAME as APP_NAME4 } from "@nextclaw/core";
8616
- var RemoteRuntimeActions = class {
8617
- constructor(deps) {
8618
- this.deps = deps;
8619
- }
8620
- async connect(opts = {}) {
8621
- await this.deps.remoteCommands.connect(opts);
8622
- }
8623
- async enable(opts = {}) {
8624
- await this.deps.initAuto("remote enable");
8625
- const result = this.deps.remoteCommands.enableConfig(opts);
8626
- console.log("\u2713 Remote access enabled");
8627
- if (result.config.remote.deviceName.trim()) {
8628
- console.log(`Device: ${result.config.remote.deviceName.trim()}`);
8629
- }
8630
- if (result.config.remote.platformApiBase.trim()) {
8631
- console.log(`Platform: ${result.config.remote.platformApiBase.trim()}`);
8632
- }
8633
- if (this.hasRunningManagedService()) {
8634
- await this.deps.restartBackgroundService("remote configuration updated");
8635
- console.log("\u2713 Applied remote settings to running background service");
8636
- return;
8637
- }
8638
- console.log(`Tip: Run "${APP_NAME4} start" to bring the managed remote connector online.`);
8639
- }
8640
- async disable() {
8641
- const result = this.deps.remoteCommands.disableConfig();
8642
- console.log(result.changed ? "\u2713 Remote access disabled" : "Remote access was already disabled");
8643
- if (this.hasRunningManagedService()) {
8644
- await this.deps.restartBackgroundService("remote access disabled");
8645
- console.log("\u2713 Running background service restarted without remote access");
8646
- }
8647
- }
8648
- async status(opts = {}) {
8649
- await this.deps.remoteCommands.status(opts);
8650
- }
8651
- async doctor(opts = {}) {
8652
- await this.deps.remoteCommands.doctor(opts);
8653
- }
8654
- hasRunningManagedService() {
8655
- const state = readServiceState();
8656
- return Boolean(state && isProcessRunning(state.pid));
8657
- }
8658
- };
8659
-
8660
8087
  // src/cli/workspace.ts
8661
- import { cpSync as cpSync3, existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync10, readdirSync as readdirSync3, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
8088
+ import { cpSync as cpSync3, existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync9, readdirSync as readdirSync3, rmSync as rmSync5, writeFileSync as writeFileSync5 } from "fs";
8662
8089
  import { createRequire as createRequire2 } from "module";
8663
- import { dirname as dirname4, join as join8, resolve as resolve11 } from "path";
8090
+ import { dirname as dirname3, join as join7, resolve as resolve11 } from "path";
8664
8091
  import { fileURLToPath as fileURLToPath4 } from "url";
8665
- import { APP_NAME as APP_NAME5, getDataDir as getDataDir8 } from "@nextclaw/core";
8092
+ import { APP_NAME as APP_NAME4, getDataDir as getDataDir8 } from "@nextclaw/core";
8666
8093
  import { spawnSync as spawnSync3 } from "child_process";
8667
8094
  var WorkspaceManager = class {
8668
8095
  constructor(logo) {
@@ -8690,30 +8117,30 @@ var WorkspaceManager = class {
8690
8117
  { source: "memory/MEMORY.md", target: "memory/MEMORY.md" }
8691
8118
  ];
8692
8119
  for (const entry of templateFiles) {
8693
- const filePath = join8(workspace, entry.target);
8694
- if (!force && existsSync12(filePath)) {
8120
+ const filePath = join7(workspace, entry.target);
8121
+ if (!force && existsSync11(filePath)) {
8695
8122
  continue;
8696
8123
  }
8697
- const templatePath = join8(templateDir, entry.source);
8698
- if (!existsSync12(templatePath)) {
8124
+ const templatePath = join7(templateDir, entry.source);
8125
+ if (!existsSync11(templatePath)) {
8699
8126
  console.warn(`Warning: Template file missing: ${templatePath}`);
8700
8127
  continue;
8701
8128
  }
8702
- const raw = readFileSync10(templatePath, "utf-8");
8703
- const content = raw.replace(/\$\{APP_NAME\}/g, APP_NAME5);
8704
- mkdirSync7(dirname4(filePath), { recursive: true });
8705
- writeFileSync6(filePath, content);
8129
+ const raw = readFileSync9(templatePath, "utf-8");
8130
+ const content = raw.replace(/\$\{APP_NAME\}/g, APP_NAME4);
8131
+ mkdirSync6(dirname3(filePath), { recursive: true });
8132
+ writeFileSync5(filePath, content);
8706
8133
  created.push(entry.target);
8707
8134
  }
8708
- const memoryDir = join8(workspace, "memory");
8709
- if (!existsSync12(memoryDir)) {
8710
- mkdirSync7(memoryDir, { recursive: true });
8711
- created.push(join8("memory", ""));
8135
+ const memoryDir = join7(workspace, "memory");
8136
+ if (!existsSync11(memoryDir)) {
8137
+ mkdirSync6(memoryDir, { recursive: true });
8138
+ created.push(join7("memory", ""));
8712
8139
  }
8713
- const skillsDir = join8(workspace, "skills");
8714
- if (!existsSync12(skillsDir)) {
8715
- mkdirSync7(skillsDir, { recursive: true });
8716
- created.push(join8("skills", ""));
8140
+ const skillsDir = join7(workspace, "skills");
8141
+ if (!existsSync11(skillsDir)) {
8142
+ mkdirSync6(skillsDir, { recursive: true });
8143
+ created.push(join7("skills", ""));
8717
8144
  }
8718
8145
  const seeded = this.seedBuiltinSkills(skillsDir, { force });
8719
8146
  if (seeded > 0) {
@@ -8732,12 +8159,12 @@ var WorkspaceManager = class {
8732
8159
  if (!entry.isDirectory()) {
8733
8160
  continue;
8734
8161
  }
8735
- const src = join8(sourceDir, entry.name);
8736
- if (!existsSync12(join8(src, "SKILL.md"))) {
8162
+ const src = join7(sourceDir, entry.name);
8163
+ if (!existsSync11(join7(src, "SKILL.md"))) {
8737
8164
  continue;
8738
8165
  }
8739
- const dest = join8(targetDir, entry.name);
8740
- if (!force && existsSync12(dest)) {
8166
+ const dest = join7(targetDir, entry.name);
8167
+ if (!force && existsSync11(dest)) {
8741
8168
  continue;
8742
8169
  }
8743
8170
  try {
@@ -8754,13 +8181,13 @@ var WorkspaceManager = class {
8754
8181
  try {
8755
8182
  const require3 = createRequire2(import.meta.url);
8756
8183
  const entry = require3.resolve("@nextclaw/core");
8757
- const pkgRoot = resolve11(dirname4(entry), "..");
8758
- const distSkills = join8(pkgRoot, "dist", "skills");
8759
- if (existsSync12(distSkills)) {
8184
+ const pkgRoot = resolve11(dirname3(entry), "..");
8185
+ const distSkills = join7(pkgRoot, "dist", "skills");
8186
+ if (existsSync11(distSkills)) {
8760
8187
  return distSkills;
8761
8188
  }
8762
- const srcSkills = join8(pkgRoot, "src", "agent", "skills");
8763
- if (existsSync12(srcSkills)) {
8189
+ const srcSkills = join7(pkgRoot, "src", "agent", "skills");
8190
+ if (existsSync11(srcSkills)) {
8764
8191
  return srcSkills;
8765
8192
  }
8766
8193
  return null;
@@ -8775,17 +8202,17 @@ var WorkspaceManager = class {
8775
8202
  }
8776
8203
  const cliDir = resolve11(fileURLToPath4(new URL(".", import.meta.url)));
8777
8204
  const pkgRoot = resolve11(cliDir, "..", "..");
8778
- const candidates = [join8(pkgRoot, "templates")];
8205
+ const candidates = [join7(pkgRoot, "templates")];
8779
8206
  for (const candidate of candidates) {
8780
- if (existsSync12(candidate)) {
8207
+ if (existsSync11(candidate)) {
8781
8208
  return candidate;
8782
8209
  }
8783
8210
  }
8784
8211
  return null;
8785
8212
  }
8786
8213
  getBridgeDir() {
8787
- const userBridge = join8(getDataDir8(), "bridge");
8788
- if (existsSync12(join8(userBridge, "dist", "index.js"))) {
8214
+ const userBridge = join7(getDataDir8(), "bridge");
8215
+ if (existsSync11(join7(userBridge, "dist", "index.js"))) {
8789
8216
  return userBridge;
8790
8217
  }
8791
8218
  if (!which("npm")) {
@@ -8794,21 +8221,21 @@ var WorkspaceManager = class {
8794
8221
  }
8795
8222
  const cliDir = resolve11(fileURLToPath4(new URL(".", import.meta.url)));
8796
8223
  const pkgRoot = resolve11(cliDir, "..", "..");
8797
- const pkgBridge = join8(pkgRoot, "bridge");
8798
- const srcBridge = join8(pkgRoot, "..", "..", "bridge");
8224
+ const pkgBridge = join7(pkgRoot, "bridge");
8225
+ const srcBridge = join7(pkgRoot, "..", "..", "bridge");
8799
8226
  let source = null;
8800
- if (existsSync12(join8(pkgBridge, "package.json"))) {
8227
+ if (existsSync11(join7(pkgBridge, "package.json"))) {
8801
8228
  source = pkgBridge;
8802
- } else if (existsSync12(join8(srcBridge, "package.json"))) {
8229
+ } else if (existsSync11(join7(srcBridge, "package.json"))) {
8803
8230
  source = srcBridge;
8804
8231
  }
8805
8232
  if (!source) {
8806
- console.error(`Bridge source not found. Try reinstalling ${APP_NAME5}.`);
8233
+ console.error(`Bridge source not found. Try reinstalling ${APP_NAME4}.`);
8807
8234
  process.exit(1);
8808
8235
  }
8809
8236
  console.log(`${this.logo} Setting up bridge...`);
8810
- mkdirSync7(resolve11(userBridge, ".."), { recursive: true });
8811
- if (existsSync12(userBridge)) {
8237
+ mkdirSync6(resolve11(userBridge, ".."), { recursive: true });
8238
+ if (existsSync11(userBridge)) {
8812
8239
  rmSync5(userBridge, { recursive: true, force: true });
8813
8240
  }
8814
8241
  cpSync3(source, userBridge, {
@@ -8886,9 +8313,14 @@ var CliRuntime = class {
8886
8313
  this.platformAuthCommands = new PlatformAuthCommands();
8887
8314
  this.remoteCommands = new RemoteCommands();
8888
8315
  this.remote = new RemoteRuntimeActions({
8316
+ appName: APP_NAME5,
8889
8317
  initAuto: (source) => this.init({ source, auto: true }),
8890
8318
  remoteCommands: this.remoteCommands,
8891
- restartBackgroundService: (reason) => this.restartBackgroundService(reason)
8319
+ restartBackgroundService: (reason) => this.restartBackgroundService(reason),
8320
+ hasRunningManagedService: () => {
8321
+ const state = readServiceState();
8322
+ return Boolean(state && isProcessRunning(state.pid));
8323
+ }
8892
8324
  });
8893
8325
  this.diagnosticsCommands = new DiagnosticsCommands({ logo: this.logo });
8894
8326
  this.restartCoordinator = new RestartCoordinator({
@@ -8920,7 +8352,7 @@ var CliRuntime = class {
8920
8352
  const uiHost = FORCED_PUBLIC_UI_HOST;
8921
8353
  const uiPort = typeof state.uiPort === "number" && Number.isFinite(state.uiPort) ? state.uiPort : 18791;
8922
8354
  console.log(
8923
- `Applying changes (${reason}): restarting ${APP_NAME6} background service...`
8355
+ `Applying changes (${reason}): restarting ${APP_NAME5} background service...`
8924
8356
  );
8925
8357
  await this.serviceCommands.stopService();
8926
8358
  await this.serviceCommands.startService({
@@ -9075,7 +8507,7 @@ var CliRuntime = class {
9075
8507
  }
9076
8508
  async onboard() {
9077
8509
  console.warn(
9078
- `Warning: ${APP_NAME6} onboard is deprecated. Use "${APP_NAME6} init" instead.`
8510
+ `Warning: ${APP_NAME5} onboard is deprecated. Use "${APP_NAME5} init" instead.`
9079
8511
  );
9080
8512
  await this.init({ source: "onboard" });
9081
8513
  }
@@ -9085,16 +8517,16 @@ var CliRuntime = class {
9085
8517
  const force = Boolean(options.force);
9086
8518
  const configPath = getConfigPath7();
9087
8519
  let createdConfig = false;
9088
- if (!existsSync13(configPath)) {
8520
+ if (!existsSync12(configPath)) {
9089
8521
  const config3 = ConfigSchema2.parse({});
9090
8522
  saveConfig10(config3);
9091
8523
  createdConfig = true;
9092
8524
  }
9093
- const config2 = loadConfig15();
8525
+ const config2 = loadConfig14();
9094
8526
  const workspaceSetting = config2.agents.defaults.workspace;
9095
- const workspacePath = !workspaceSetting || workspaceSetting === DEFAULT_WORKSPACE_PATH ? join9(getDataDir9(), DEFAULT_WORKSPACE_DIR) : expandHome2(workspaceSetting);
9096
- const workspaceExisted = existsSync13(workspacePath);
9097
- mkdirSync8(workspacePath, { recursive: true });
8527
+ const workspacePath = !workspaceSetting || workspaceSetting === DEFAULT_WORKSPACE_PATH ? join8(getDataDir9(), DEFAULT_WORKSPACE_DIR) : expandHome2(workspaceSetting);
8528
+ const workspaceExisted = existsSync12(workspacePath);
8529
+ mkdirSync7(workspacePath, { recursive: true });
9098
8530
  const templateResult = this.workspaceManager.createWorkspaceTemplates(
9099
8531
  workspacePath,
9100
8532
  { force }
@@ -9113,13 +8545,13 @@ var CliRuntime = class {
9113
8545
  }
9114
8546
  if (!options.auto) {
9115
8547
  console.log(`
9116
- ${this.logo} ${APP_NAME6} is ready! (${source})`);
8548
+ ${this.logo} ${APP_NAME5} is ready! (${source})`);
9117
8549
  console.log("\nNext steps:");
9118
8550
  console.log(` 1. Add your API key to ${configPath}`);
9119
- console.log(` 2. Chat: ${APP_NAME6} agent -m "Hello!"`);
8551
+ console.log(` 2. Chat: ${APP_NAME5} agent -m "Hello!"`);
9120
8552
  } else {
9121
8553
  console.log(
9122
- `Tip: Run "${APP_NAME6} init${force ? " --force" : ""}" to re-run initialization if needed.`
8554
+ `Tip: Run "${APP_NAME5} init${force ? " --force" : ""}" to re-run initialization if needed.`
9123
8555
  );
9124
8556
  }
9125
8557
  }
@@ -9177,7 +8609,7 @@ ${this.logo} ${APP_NAME6} is ready! (${source})`);
9177
8609
  await this.writeRestartSentinelFromExecContext("cli.restart");
9178
8610
  const state = readServiceState();
9179
8611
  if (state && isProcessRunning(state.pid)) {
9180
- console.log(`Restarting ${APP_NAME6}...`);
8612
+ console.log(`Restarting ${APP_NAME5}...`);
9181
8613
  await this.serviceCommands.stopService();
9182
8614
  } else if (state) {
9183
8615
  clearServiceState();
@@ -9217,7 +8649,7 @@ ${this.logo} ${APP_NAME6} is ready! (${source})`);
9217
8649
  }
9218
8650
  async agent(opts) {
9219
8651
  const configPath = getConfigPath7();
9220
- const config2 = resolveConfigSecrets3(loadConfig15(), { configPath });
8652
+ const config2 = resolveConfigSecrets3(loadConfig14(), { configPath });
9221
8653
  const workspace = getWorkspacePath10(config2.agents.defaults.workspace);
9222
8654
  const pluginRegistry = loadPluginRegistry(config2, workspace);
9223
8655
  const extensionRegistry = toExtensionRegistry(pluginRegistry);
@@ -9225,7 +8657,7 @@ ${this.logo} ${APP_NAME6} is ready! (${source})`);
9225
8657
  const pluginChannelBindings = getPluginChannelBindings4(pluginRegistry);
9226
8658
  setPluginRuntimeBridge2({
9227
8659
  loadConfig: () => toPluginConfigView(
9228
- resolveConfigSecrets3(loadConfig15(), { configPath }),
8660
+ resolveConfigSecrets3(loadConfig14(), { configPath }),
9229
8661
  pluginChannelBindings
9230
8662
  ),
9231
8663
  writeConfigFile: async (nextConfigView) => {
@@ -9234,7 +8666,7 @@ ${this.logo} ${APP_NAME6} is ready! (${source})`);
9234
8666
  "plugin runtime writeConfigFile expects an object config"
9235
8667
  );
9236
8668
  }
9237
- const current = loadConfig15();
8669
+ const current = loadConfig14();
9238
8670
  const next = mergePluginConfigView(
9239
8671
  current,
9240
8672
  nextConfigView,
@@ -9266,7 +8698,7 @@ ${this.logo} ${APP_NAME6} is ready! (${source})`);
9266
8698
  resolveMessageToolHints: ({ channel, accountId }) => resolvePluginChannelMessageToolHints2({
9267
8699
  registry: pluginRegistry,
9268
8700
  channel,
9269
- cfg: resolveConfigSecrets3(loadConfig15(), { configPath }),
8701
+ cfg: resolveConfigSecrets3(loadConfig14(), { configPath }),
9270
8702
  accountId
9271
8703
  })
9272
8704
  });
@@ -9285,10 +8717,10 @@ ${this.logo} ${APP_NAME6} is ready! (${source})`);
9285
8717
  `${this.logo} Interactive mode (type exit or Ctrl+C to quit)
9286
8718
  `
9287
8719
  );
9288
- const historyFile = join9(getDataDir9(), "history", "cli_history");
8720
+ const historyFile = join8(getDataDir9(), "history", "cli_history");
9289
8721
  const historyDir = resolve12(historyFile, "..");
9290
- mkdirSync8(historyDir, { recursive: true });
9291
- const history = existsSync13(historyFile) ? readFileSync11(historyFile, "utf-8").split("\n").filter(Boolean) : [];
8722
+ mkdirSync7(historyDir, { recursive: true });
8723
+ const history = existsSync12(historyFile) ? readFileSync10(historyFile, "utf-8").split("\n").filter(Boolean) : [];
9292
8724
  const rl = createInterface3({
9293
8725
  input: process.stdin,
9294
8726
  output: process.stdout
@@ -9297,7 +8729,7 @@ ${this.logo} ${APP_NAME6} is ready! (${source})`);
9297
8729
  const merged = history.concat(
9298
8730
  rl.history ?? []
9299
8731
  );
9300
- writeFileSync7(historyFile, merged.join("\n"));
8732
+ writeFileSync6(historyFile, merged.join("\n"));
9301
8733
  process.exit(0);
9302
8734
  });
9303
8735
  let running = true;
@@ -9367,7 +8799,7 @@ ${this.logo} ${APP_NAME6} is ready! (${source})`);
9367
8799
  }
9368
8800
  const state = readServiceState();
9369
8801
  if (state && isProcessRunning(state.pid)) {
9370
- console.log(`Tip: restart ${APP_NAME6} to apply the update.`);
8802
+ console.log(`Tip: restart ${APP_NAME5} to apply the update.`);
9371
8803
  }
9372
8804
  }
9373
8805
  pluginsList(opts = {}) {
@@ -9461,7 +8893,7 @@ ${this.logo} ${APP_NAME6} is ready! (${source})`);
9461
8893
  await this.diagnosticsCommands.doctor(opts);
9462
8894
  }
9463
8895
  async skillsInstall(options) {
9464
- const config2 = loadConfig15();
8896
+ const config2 = loadConfig14();
9465
8897
  const workdir = resolveSkillsInstallWorkdir({
9466
8898
  explicitWorkdir: options.workdir,
9467
8899
  configuredWorkspace: config2.agents.defaults.workspace
@@ -9522,32 +8954,22 @@ ${this.logo} ${APP_NAME6} is ready! (${source})`);
9522
8954
  }
9523
8955
  };
9524
8956
 
9525
- // src/cli/remote/register-remote-commands.ts
9526
- function registerRemoteCommands(program2, runtime2) {
9527
- const remote = program2.command("remote").description("Manage remote access");
9528
- remote.command("enable").description("Enable service-managed remote access").option("--api-base <url>", "Platform API base (supports /v1 suffix)").option("--name <name>", "Device display name").action(async (opts) => runtime2.enable(opts));
9529
- remote.command("disable").description("Disable service-managed remote access").action(async () => runtime2.disable());
9530
- remote.command("status").description("Show remote access status").option("--json", "Print JSON").action(async (opts) => runtime2.status(opts));
9531
- remote.command("doctor").description("Run remote access diagnostics").option("--json", "Print JSON").action(async (opts) => runtime2.doctor(opts));
9532
- remote.command("connect").description("Foreground debug mode: register this machine and keep the connector online").option("--api-base <url>", "Platform API base (supports /v1 suffix)").option("--local-origin <url>", "Local NextClaw UI origin (default: active service or http://127.0.0.1:18791)").option("--name <name>", "Device display name").option("--once", "Connect once without auto-reconnect", false).action(async (opts) => runtime2.connect(opts));
9533
- }
9534
-
9535
8957
  // src/cli/index.ts
9536
8958
  var program = new Command();
9537
8959
  var runtime = new CliRuntime({ logo: LOGO });
9538
- program.name(APP_NAME7).description(`${LOGO} ${APP_NAME7} - ${APP_TAGLINE}`).version(getPackageVersion(), "-v, --version", "show version");
9539
- program.command("onboard").description(`Initialize ${APP_NAME7} configuration and workspace`).action(async () => runtime.onboard());
9540
- program.command("init").description(`Initialize ${APP_NAME7} configuration and workspace`).option("-f, --force", "Overwrite existing template files").action(async (opts) => runtime.init({ force: Boolean(opts.force) }));
8960
+ program.name(APP_NAME6).description(`${LOGO} ${APP_NAME6} - ${APP_TAGLINE}`).version(getPackageVersion(), "-v, --version", "show version");
8961
+ program.command("onboard").description(`Initialize ${APP_NAME6} configuration and workspace`).action(async () => runtime.onboard());
8962
+ program.command("init").description(`Initialize ${APP_NAME6} configuration and workspace`).option("-f, --force", "Overwrite existing template files").action(async (opts) => runtime.init({ force: Boolean(opts.force) }));
9541
8963
  program.command("login").description("Login to NextClaw platform and save token into providers.nextclaw.apiKey").option("--api-base <url>", "Platform API base (supports /v1 suffix)").option("--email <email>", "Login email").option("--password <password>", "Login password").option("--register", "Register first, then login", false).action(async (opts) => runtime.login(opts));
9542
8964
  registerRemoteCommands(program, runtime.remote);
9543
- program.command("gateway").description(`Start the ${APP_NAME7} gateway`).option("-p, --port <port>", "Gateway port", "18790").option("-v, --verbose", "Verbose output", false).option("--ui", "Enable UI server", false).option("--ui-port <port>", "UI port").option("--ui-open", "Open browser when UI starts", false).action(async (opts) => runtime.gateway(opts));
9544
- program.command("ui").description(`Start the ${APP_NAME7} UI with gateway`).option("--port <port>", "UI port").option("--no-open", "Disable opening browser").action(async (opts) => runtime.ui(opts));
9545
- program.command("start").description(`Start the ${APP_NAME7} gateway + UI in the background`).option("--ui-port <port>", "UI port").option("--start-timeout <ms>", "Maximum wait time for startup readiness in milliseconds").option("--open", "Open browser after start", false).action(async (opts) => runtime.start(opts));
9546
- program.command("restart").description(`Restart the ${APP_NAME7} background service`).option("--ui-port <port>", "UI port").option("--start-timeout <ms>", "Maximum wait time for startup readiness in milliseconds").option("--open", "Open browser after restart", false).action(async (opts) => runtime.restart(opts));
9547
- program.command("serve").description(`Run the ${APP_NAME7} gateway + UI in the foreground`).option("--ui-port <port>", "UI port").option("--open", "Open browser after start", false).action(async (opts) => runtime.serve(opts));
9548
- program.command("stop").description(`Stop the ${APP_NAME7} background service`).action(async () => runtime.stop());
8965
+ program.command("gateway").description(`Start the ${APP_NAME6} gateway`).option("-p, --port <port>", "Gateway port", "18790").option("-v, --verbose", "Verbose output", false).option("--ui", "Enable UI server", false).option("--ui-port <port>", "UI port").option("--ui-open", "Open browser when UI starts", false).action(async (opts) => runtime.gateway(opts));
8966
+ program.command("ui").description(`Start the ${APP_NAME6} UI with gateway`).option("--port <port>", "UI port").option("--no-open", "Disable opening browser").action(async (opts) => runtime.ui(opts));
8967
+ program.command("start").description(`Start the ${APP_NAME6} gateway + UI in the background`).option("--ui-port <port>", "UI port").option("--start-timeout <ms>", "Maximum wait time for startup readiness in milliseconds").option("--open", "Open browser after start", false).action(async (opts) => runtime.start(opts));
8968
+ program.command("restart").description(`Restart the ${APP_NAME6} background service`).option("--ui-port <port>", "UI port").option("--start-timeout <ms>", "Maximum wait time for startup readiness in milliseconds").option("--open", "Open browser after restart", false).action(async (opts) => runtime.restart(opts));
8969
+ program.command("serve").description(`Run the ${APP_NAME6} gateway + UI in the foreground`).option("--ui-port <port>", "UI port").option("--open", "Open browser after start", false).action(async (opts) => runtime.serve(opts));
8970
+ program.command("stop").description(`Stop the ${APP_NAME6} background service`).action(async () => runtime.stop());
9549
8971
  program.command("agent").description("Interact with the agent directly").option("-m, --message <message>", "Message to send to the agent").option("-s, --session <session>", "Session ID", "cli:default").option("--model <model>", "Session model override for this run").option("--no-markdown", "Disable Markdown rendering").action(async (opts) => runtime.agent(opts));
9550
- program.command("update").description(`Update ${APP_NAME7}`).option("--timeout <ms>", "Update command timeout in milliseconds").action(async (opts) => runtime.update(opts));
8972
+ program.command("update").description(`Update ${APP_NAME6}`).option("--timeout <ms>", "Update command timeout in milliseconds").action(async (opts) => runtime.update(opts));
9551
8973
  var skills = program.command("skills").description("Manage skills");
9552
8974
  skills.command("install <slug>").description("Install a skill from NextClaw marketplace").option("--api-base <url>", "Marketplace API base URL").option("--workdir <dir>", "Workspace directory to install into").option("--dir <dir>", "Skills directory name (default: skills)").option("-f, --force", "Overwrite existing skill files", false).action(async (slug, opts) => runtime.skillsInstall({ slug, ...opts, apiBaseUrl: opts.apiBase }));
9553
8975
  var withRepeatableTag = (value, previous = []) => [...previous, value];
@@ -9592,6 +9014,6 @@ cron.command("add").requiredOption("-n, --name <name>", "Job name").requiredOpti
9592
9014
  cron.command("remove <jobId>").action((jobId) => runtime.cronRemove(jobId));
9593
9015
  cron.command("enable <jobId>").option("--disable", "Disable instead of enable").action((jobId, opts) => runtime.cronEnable(jobId, opts));
9594
9016
  cron.command("run <jobId>").option("-f, --force", "Run even if disabled").action(async (jobId, opts) => runtime.cronRun(jobId, opts));
9595
- program.command("status").description(`Show ${APP_NAME7} status`).option("--json", "Output JSON", false).option("--verbose", "Show extra diagnostics", false).option("--fix", "Fix stale service state when safe", false).action(async (opts) => runtime.status(opts));
9596
- program.command("doctor").description(`Run ${APP_NAME7} diagnostics`).option("--json", "Output JSON", false).option("--verbose", "Show extra diagnostics", false).option("--fix", "Fix stale service state when safe", false).action(async (opts) => runtime.doctor(opts));
9017
+ program.command("status").description(`Show ${APP_NAME6} status`).option("--json", "Output JSON", false).option("--verbose", "Show extra diagnostics", false).option("--fix", "Fix stale service state when safe", false).action(async (opts) => runtime.status(opts));
9018
+ program.command("doctor").description(`Run ${APP_NAME6} diagnostics`).option("--json", "Output JSON", false).option("--verbose", "Show extra diagnostics", false).option("--fix", "Fix stale service state when safe", false).action(async (opts) => runtime.doctor(opts));
9597
9019
  program.parseAsync(process.argv);