nextclaw 0.13.9 → 0.13.11
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 +235 -53
- package/package.json +22 -21
- package/ui-dist/assets/ChannelsList-Byfj2R01.js +1 -0
- package/ui-dist/assets/ChatPage-DM1ewbWf.js +38 -0
- package/ui-dist/assets/DocBrowser-BLv77lJ0.js +1 -0
- package/ui-dist/assets/LogoBadge-D7j1al-w.js +1 -0
- package/ui-dist/assets/MarketplacePage-DuskLKYh.js +49 -0
- package/ui-dist/assets/McpMarketplacePage-DpMjaD3m.js +40 -0
- package/ui-dist/assets/ModelConfig-ubaecweS.js +1 -0
- package/ui-dist/assets/ProvidersList-w8MJH2LI.js +1 -0
- package/ui-dist/assets/RemoteAccessPage-D79_5Kbn.js +1 -0
- package/ui-dist/assets/RuntimeConfig-BbX4yFKy.js +1 -0
- package/ui-dist/assets/SearchConfig-BmmmeyJd.js +1 -0
- package/ui-dist/assets/SecretsConfig-CWG8J01H.js +3 -0
- package/ui-dist/assets/SessionsConfig-D-vg_Lgv.js +2 -0
- package/ui-dist/assets/chat-message-CGXiVhyN.js +3 -0
- package/ui-dist/assets/config-hints-CApS3K_7.js +1 -0
- package/ui-dist/assets/config-layout-BHnOoweL.js +1 -0
- package/ui-dist/assets/index-COrhpAdh.css +1 -0
- package/ui-dist/assets/index-CeRbsQ90.js +8 -0
- package/ui-dist/assets/index-Ct7FQpxN.js +1 -0
- package/ui-dist/assets/label-CCSffS1D.js +1 -0
- package/ui-dist/assets/marketplace-localization-Dk31LJJJ.js +1 -0
- package/ui-dist/assets/page-layout-ud8wZ8gX.js +1 -0
- package/ui-dist/assets/popover-Bfoe6YBX.js +1 -0
- package/ui-dist/assets/provider-models-D3B_xWXx.js +1 -0
- package/ui-dist/assets/security-config-DJJUCMov.js +1 -0
- package/ui-dist/assets/skeleton-IOOTmHzP.js +1 -0
- package/ui-dist/assets/status-dot-Fz9-eKsl.js +1 -0
- package/ui-dist/assets/switch-B-_SrMSL.js +1 -0
- package/ui-dist/assets/tabs-custom-6Tm1ZHfS.js +1 -0
- package/ui-dist/assets/useConfirmDialog-BeOW2bOI.js +5 -0
- package/ui-dist/assets/vendor-CwsIoNvJ.js +442 -0
- package/ui-dist/index.html +18 -0
- package/LICENSE +0 -21
package/dist/cli/index.js
CHANGED
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
setPluginRuntimeBridge as setPluginRuntimeBridge2
|
|
30
30
|
} from "@nextclaw/openclaw-compat";
|
|
31
31
|
import { existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
|
|
32
|
-
import { join as
|
|
32
|
+
import { join as join9, resolve as resolve12 } from "path";
|
|
33
33
|
import { createInterface as createInterface3 } from "readline";
|
|
34
34
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
35
35
|
import { spawn as spawn4 } from "child_process";
|
|
@@ -3001,6 +3001,73 @@ 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
3072
|
async loginResult(opts = {}) {
|
|
3006
3073
|
const { configPath, config: config2, providers, nextclawProvider, platformBase, v1Base, inputApiBase } = resolveProviderConfig(opts);
|
|
@@ -3015,20 +3082,17 @@ 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
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3088
|
+
persistPlatformToken({
|
|
3089
|
+
configPath,
|
|
3090
|
+
config: config2,
|
|
3091
|
+
providers,
|
|
3092
|
+
nextclawProvider,
|
|
3093
|
+
v1Base,
|
|
3094
|
+
token
|
|
3095
|
+
});
|
|
3032
3096
|
return {
|
|
3033
3097
|
token,
|
|
3034
3098
|
role,
|
|
@@ -3037,6 +3101,73 @@ var PlatformAuthCommands = class {
|
|
|
3037
3101
|
v1Base
|
|
3038
3102
|
};
|
|
3039
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
|
+
}
|
|
3040
3171
|
async login(opts = {}) {
|
|
3041
3172
|
const result = await this.loginResult(opts);
|
|
3042
3173
|
console.log(`\u2713 Logged in to NextClaw platform (${result.platformBase})`);
|
|
@@ -3130,6 +3261,9 @@ function normalizeOptionalString3(value) {
|
|
|
3130
3261
|
const trimmed = value.trim();
|
|
3131
3262
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
3132
3263
|
}
|
|
3264
|
+
function isPlatformSessionToken(value) {
|
|
3265
|
+
return typeof value === "string" && value.startsWith("nca.");
|
|
3266
|
+
}
|
|
3133
3267
|
function resolveConfiguredLocalOrigin(config2) {
|
|
3134
3268
|
const state = readServiceState();
|
|
3135
3269
|
if (state && isProcessRunning(state.pid) && Number.isFinite(state.uiPort)) {
|
|
@@ -3240,8 +3374,8 @@ var RemoteCommands = class {
|
|
|
3240
3374
|
},
|
|
3241
3375
|
{
|
|
3242
3376
|
name: "platform-token",
|
|
3243
|
-
ok:
|
|
3244
|
-
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'
|
|
3245
3379
|
},
|
|
3246
3380
|
{
|
|
3247
3381
|
name: "platform-api-base",
|
|
@@ -3281,7 +3415,7 @@ var RemoteCommands = class {
|
|
|
3281
3415
|
// src/cli/commands/diagnostics.ts
|
|
3282
3416
|
import { createServer as createNetServer } from "net";
|
|
3283
3417
|
import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
|
|
3284
|
-
import { resolve as resolve8 } from "path";
|
|
3418
|
+
import { join as join4, resolve as resolve8 } from "path";
|
|
3285
3419
|
import {
|
|
3286
3420
|
APP_NAME as APP_NAME2,
|
|
3287
3421
|
getConfigPath as getConfigPath5,
|
|
@@ -3422,6 +3556,11 @@ var DiagnosticsCommands = class {
|
|
|
3422
3556
|
status: report.workspaceExists ? "pass" : "warn",
|
|
3423
3557
|
detail: report.workspacePath
|
|
3424
3558
|
},
|
|
3559
|
+
{
|
|
3560
|
+
name: "ui-assets",
|
|
3561
|
+
status: report.uiAssets.indexHtmlPresent ? "pass" : "fail",
|
|
3562
|
+
detail: report.uiAssets.resolvedStaticDir ? `${report.uiAssets.resolvedStaticDir} (${report.uiAssets.indexHtmlPresent ? "index.html found" : "index.html missing"})` : "no UI static directory resolved"
|
|
3563
|
+
},
|
|
3425
3564
|
{
|
|
3426
3565
|
name: "service-state",
|
|
3427
3566
|
status: report.process.staleState ? "fail" : report.process.running ? "pass" : "warn",
|
|
@@ -3490,6 +3629,8 @@ var DiagnosticsCommands = class {
|
|
|
3490
3629
|
const configuredUi = resolveUiConfig(config2, { enabled: true, host: config2.ui.host, port: config2.ui.port });
|
|
3491
3630
|
const configuredUiUrl = resolveUiApiBase(configuredUi.host, configuredUi.port);
|
|
3492
3631
|
const configuredApiUrl = `${configuredUiUrl}/api`;
|
|
3632
|
+
const resolvedStaticDir = serviceState?.uiStaticDir ?? resolveUiStaticDir();
|
|
3633
|
+
const indexHtmlPresent = Boolean(resolvedStaticDir && existsSync6(join4(resolvedStaticDir, "index.html")));
|
|
3493
3634
|
const managedUiUrl = serviceState?.uiUrl ?? null;
|
|
3494
3635
|
const managedApiUrl = serviceState?.apiUrl ?? null;
|
|
3495
3636
|
const managedHealth = running && managedApiUrl ? await this.probeApiHealth(`${managedApiUrl}/health`) : { state: "unreachable", detail: "service not running" };
|
|
@@ -3524,6 +3665,10 @@ var DiagnosticsCommands = class {
|
|
|
3524
3665
|
providers,
|
|
3525
3666
|
serviceStatePath,
|
|
3526
3667
|
serviceStateExists: existsSync6(serviceStatePath),
|
|
3668
|
+
uiAssets: {
|
|
3669
|
+
resolvedStaticDir,
|
|
3670
|
+
indexHtmlPresent
|
|
3671
|
+
},
|
|
3527
3672
|
fixActions,
|
|
3528
3673
|
process: {
|
|
3529
3674
|
managedByState,
|
|
@@ -3623,7 +3768,11 @@ var DiagnosticsCommands = class {
|
|
|
3623
3768
|
params.issues.push("A service appears healthy on configured API endpoint, but state is missing/stale.");
|
|
3624
3769
|
params.recommendations.push("Another process may be occupying the UI port; stop it or use --ui-port with a free port.");
|
|
3625
3770
|
}
|
|
3626
|
-
if (
|
|
3771
|
+
if (params.running && !params.serviceState?.uiStaticDir) {
|
|
3772
|
+
params.issues.push("Managed service did not record a resolved UI static asset directory.");
|
|
3773
|
+
params.recommendations.push(`Check logs at ${params.serviceState?.logPath ?? resolveServiceLogPath()} and verify packaged ui-dist assets exist.`);
|
|
3774
|
+
}
|
|
3775
|
+
if (!params.running && !params.providers.some((provider) => provider.configured)) {
|
|
3627
3776
|
params.recommendations.push("Configure at least one provider API key in UI or config before expecting agent replies.");
|
|
3628
3777
|
}
|
|
3629
3778
|
}
|
|
@@ -3673,7 +3822,7 @@ import {
|
|
|
3673
3822
|
} from "@nextclaw/openclaw-compat";
|
|
3674
3823
|
import { startUiServer } from "@nextclaw/server";
|
|
3675
3824
|
import { appendFileSync, closeSync, cpSync as cpSync2, existsSync as existsSync10, mkdirSync as mkdirSync5, openSync } from "fs";
|
|
3676
|
-
import { dirname as dirname2, join as
|
|
3825
|
+
import { dirname as dirname2, join as join7, resolve as resolve10 } from "path";
|
|
3677
3826
|
import { spawn as spawn3 } from "child_process";
|
|
3678
3827
|
import { request as httpRequest } from "http";
|
|
3679
3828
|
import { request as httpsRequest } from "https";
|
|
@@ -4154,7 +4303,7 @@ var MissingProvider = class extends LLMProvider {
|
|
|
4154
4303
|
// src/cli/commands/service-marketplace-installer.ts
|
|
4155
4304
|
import { getWorkspacePath as getWorkspacePath5, loadConfig as loadConfig12 } from "@nextclaw/core";
|
|
4156
4305
|
import { existsSync as existsSync8, rmSync as rmSync4 } from "fs";
|
|
4157
|
-
import { join as
|
|
4306
|
+
import { join as join5 } from "path";
|
|
4158
4307
|
|
|
4159
4308
|
// src/cli/commands/service-marketplace-helpers.ts
|
|
4160
4309
|
var containsAbsoluteFsPath = (line) => {
|
|
@@ -4357,7 +4506,7 @@ var ServiceMarketplaceInstaller = class {
|
|
|
4357
4506
|
}
|
|
4358
4507
|
async uninstallSkill(slug) {
|
|
4359
4508
|
const workspace = getWorkspacePath5(loadConfig12().agents.defaults.workspace);
|
|
4360
|
-
const targetDir =
|
|
4509
|
+
const targetDir = join5(workspace, "skills", slug);
|
|
4361
4510
|
if (!existsSync8(targetDir)) {
|
|
4362
4511
|
throw new Error(`Skill not installed in workspace: ${slug}`);
|
|
4363
4512
|
}
|
|
@@ -6350,7 +6499,7 @@ async function createUiNcpAgent(params) {
|
|
|
6350
6499
|
// src/cli/commands/service-remote-runtime.ts
|
|
6351
6500
|
import { RemoteServiceModule } from "@nextclaw/remote";
|
|
6352
6501
|
function createManagedRemoteModule(params) {
|
|
6353
|
-
if (!params.
|
|
6502
|
+
if (!params.uiEnabled) {
|
|
6354
6503
|
return null;
|
|
6355
6504
|
}
|
|
6356
6505
|
return new RemoteServiceModule({
|
|
@@ -6374,6 +6523,7 @@ function writeInitialManagedServiceState(params) {
|
|
|
6374
6523
|
uiHost: params.snapshot.uiHost,
|
|
6375
6524
|
uiPort: params.snapshot.uiPort,
|
|
6376
6525
|
logPath: params.snapshot.logPath,
|
|
6526
|
+
uiStaticDir: params.snapshot.uiStaticDir ?? null,
|
|
6377
6527
|
startupLastProbeError: null,
|
|
6378
6528
|
startupTimeoutMs: params.readinessTimeoutMs,
|
|
6379
6529
|
startupCheckedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -6390,6 +6540,7 @@ function writeReadyManagedServiceState(params) {
|
|
|
6390
6540
|
uiHost: params.snapshot.uiHost,
|
|
6391
6541
|
uiPort: params.snapshot.uiPort,
|
|
6392
6542
|
logPath: params.snapshot.logPath,
|
|
6543
|
+
uiStaticDir: params.snapshot.uiStaticDir ?? currentState?.uiStaticDir ?? null,
|
|
6393
6544
|
startupState: params.readiness.ready ? "ready" : "degraded",
|
|
6394
6545
|
startupLastProbeError: params.readiness.lastProbeError,
|
|
6395
6546
|
startupTimeoutMs: params.readinessTimeoutMs,
|
|
@@ -6424,6 +6575,9 @@ function decodeJwtPayload(token) {
|
|
|
6424
6575
|
return null;
|
|
6425
6576
|
}
|
|
6426
6577
|
}
|
|
6578
|
+
function isPlatformSessionToken2(token) {
|
|
6579
|
+
return typeof token === "string" && token.startsWith("nca.");
|
|
6580
|
+
}
|
|
6427
6581
|
function toRemoteRuntimeView(runtime2) {
|
|
6428
6582
|
if (!runtime2) {
|
|
6429
6583
|
return null;
|
|
@@ -6480,6 +6634,32 @@ var RemoteAccessHost = class {
|
|
|
6480
6634
|
await this.deps.platformAuthCommands.loginResult(input);
|
|
6481
6635
|
return this.getStatus();
|
|
6482
6636
|
}
|
|
6637
|
+
async startBrowserAuth(input) {
|
|
6638
|
+
const result = await this.deps.platformAuthCommands.startBrowserAuth({
|
|
6639
|
+
apiBase: input.apiBase
|
|
6640
|
+
});
|
|
6641
|
+
return {
|
|
6642
|
+
sessionId: result.sessionId,
|
|
6643
|
+
verificationUri: result.verificationUri,
|
|
6644
|
+
expiresAt: result.expiresAt,
|
|
6645
|
+
intervalMs: result.intervalMs
|
|
6646
|
+
};
|
|
6647
|
+
}
|
|
6648
|
+
async pollBrowserAuth(input) {
|
|
6649
|
+
const config2 = loadConfig13(getConfigPath6());
|
|
6650
|
+
const result = await this.deps.platformAuthCommands.pollBrowserAuth({
|
|
6651
|
+
apiBase: normalizeOptionalString5(input.apiBase) ?? normalizeOptionalString5(config2.remote.platformApiBase) ?? normalizeOptionalString5(config2.providers.nextclaw?.apiBase) ?? void 0,
|
|
6652
|
+
sessionId: input.sessionId
|
|
6653
|
+
});
|
|
6654
|
+
if (result.status !== "authorized") {
|
|
6655
|
+
return result;
|
|
6656
|
+
}
|
|
6657
|
+
return {
|
|
6658
|
+
status: "authorized",
|
|
6659
|
+
email: result.email,
|
|
6660
|
+
role: result.role
|
|
6661
|
+
};
|
|
6662
|
+
}
|
|
6483
6663
|
logout() {
|
|
6484
6664
|
this.deps.platformAuthCommands.logout();
|
|
6485
6665
|
return this.getStatus();
|
|
@@ -6592,7 +6772,7 @@ var RemoteAccessHost = class {
|
|
|
6592
6772
|
};
|
|
6593
6773
|
}
|
|
6594
6774
|
readAccountView(params) {
|
|
6595
|
-
if (!params.token) {
|
|
6775
|
+
if (!isPlatformSessionToken2(params.token)) {
|
|
6596
6776
|
return {
|
|
6597
6777
|
loggedIn: false,
|
|
6598
6778
|
apiBase: params.apiBase,
|
|
@@ -6692,13 +6872,13 @@ function createRemoteAccessHost(params) {
|
|
|
6692
6872
|
|
|
6693
6873
|
// src/cli/commands/ui-chat-run-coordinator.ts
|
|
6694
6874
|
import { existsSync as existsSync9, mkdirSync as mkdirSync4, readdirSync as readdirSync2, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
|
|
6695
|
-
import { join as
|
|
6875
|
+
import { join as join6 } from "path";
|
|
6696
6876
|
import {
|
|
6697
6877
|
getDataDir as getDataDir6,
|
|
6698
6878
|
parseAgentScopedSessionKey as parseAgentScopedSessionKey2,
|
|
6699
6879
|
safeFilename
|
|
6700
6880
|
} from "@nextclaw/core";
|
|
6701
|
-
var RUNS_DIR =
|
|
6881
|
+
var RUNS_DIR = join6(getDataDir6(), "runs");
|
|
6702
6882
|
var NON_TERMINAL_STATES = /* @__PURE__ */ new Set(["queued", "running"]);
|
|
6703
6883
|
var DEFAULT_SESSION_TYPE = "native";
|
|
6704
6884
|
var SESSION_TYPE_METADATA_KEY = "session_type";
|
|
@@ -7224,7 +7404,7 @@ var UiChatRunCoordinator = class {
|
|
|
7224
7404
|
};
|
|
7225
7405
|
}
|
|
7226
7406
|
getRunPath(runId) {
|
|
7227
|
-
return
|
|
7407
|
+
return join6(RUNS_DIR, `${safeFilename(runId)}.json`);
|
|
7228
7408
|
}
|
|
7229
7409
|
persistRun(run) {
|
|
7230
7410
|
const persisted = {
|
|
@@ -7253,7 +7433,7 @@ var UiChatRunCoordinator = class {
|
|
|
7253
7433
|
if (!entry.isFile() || !entry.name.endsWith(".json")) {
|
|
7254
7434
|
continue;
|
|
7255
7435
|
}
|
|
7256
|
-
const path2 =
|
|
7436
|
+
const path2 = join6(RUNS_DIR, entry.name);
|
|
7257
7437
|
try {
|
|
7258
7438
|
const parsed = JSON.parse(readFileSync8(path2, "utf-8"));
|
|
7259
7439
|
const runId = readOptionalString(parsed.runId);
|
|
@@ -7359,7 +7539,7 @@ var ServiceCommands = class {
|
|
|
7359
7539
|
});
|
|
7360
7540
|
const sessionManager = new SessionManager(workspace);
|
|
7361
7541
|
let pluginGatewayHandles = [];
|
|
7362
|
-
const cronStorePath =
|
|
7542
|
+
const cronStorePath = join7(getDataDir7(), "cron", "jobs.json");
|
|
7363
7543
|
const cron2 = new CronService2(cronStorePath);
|
|
7364
7544
|
const uiConfig = resolveUiConfig(config2, options.uiOverrides);
|
|
7365
7545
|
const uiStaticDir = options.uiStaticDir === void 0 ? resolveUiStaticDir() : options.uiStaticDir;
|
|
@@ -7542,7 +7722,7 @@ var ServiceCommands = class {
|
|
|
7542
7722
|
accountId
|
|
7543
7723
|
})
|
|
7544
7724
|
);
|
|
7545
|
-
const remoteModule = createManagedRemoteModule({ config: config2, localOrigin });
|
|
7725
|
+
const remoteModule = createManagedRemoteModule({ config: config2, uiEnabled: uiConfig.enabled, localOrigin });
|
|
7546
7726
|
await startGatewaySupportServices({
|
|
7547
7727
|
cronJobs: cron2.status().jobs,
|
|
7548
7728
|
remoteModule,
|
|
@@ -7755,6 +7935,8 @@ var ServiceCommands = class {
|
|
|
7755
7935
|
if (existing) {
|
|
7756
7936
|
clearServiceState();
|
|
7757
7937
|
}
|
|
7938
|
+
const staticDirDescription = staticDir ? `staticDir=${staticDir}` : "staticDir=<missing>";
|
|
7939
|
+
this.appendStartupStage(logPath, `ui asset resolution: ${staticDirDescription}`);
|
|
7758
7940
|
if (!staticDir) {
|
|
7759
7941
|
console.log("Warning: UI frontend not found in package assets.");
|
|
7760
7942
|
}
|
|
@@ -7805,7 +7987,7 @@ var ServiceCommands = class {
|
|
|
7805
7987
|
writeInitialManagedServiceState({
|
|
7806
7988
|
config: config2,
|
|
7807
7989
|
readinessTimeoutMs,
|
|
7808
|
-
snapshot: { pid: child.pid, uiUrl, apiUrl, uiHost: uiConfig.host, uiPort: uiConfig.port, logPath }
|
|
7990
|
+
snapshot: { pid: child.pid, uiUrl, apiUrl, uiHost: uiConfig.host, uiPort: uiConfig.port, logPath, uiStaticDir: staticDir }
|
|
7809
7991
|
});
|
|
7810
7992
|
this.appendStartupStage(logPath, `health probe started: ${healthUrl} (phase=quick, timeoutMs=${quickPhaseTimeoutMs})`);
|
|
7811
7993
|
let readiness = await this.waitForBackgroundServiceReady({
|
|
@@ -8333,8 +8515,8 @@ var ServiceCommands = class {
|
|
|
8333
8515
|
}
|
|
8334
8516
|
installBuiltinMarketplaceSkill(slug, force) {
|
|
8335
8517
|
const workspace = getWorkspacePath9(loadConfig14().agents.defaults.workspace);
|
|
8336
|
-
const destination =
|
|
8337
|
-
const destinationSkillFile =
|
|
8518
|
+
const destination = join7(workspace, "skills", slug);
|
|
8519
|
+
const destinationSkillFile = join7(destination, "SKILL.md");
|
|
8338
8520
|
if (existsSync10(destinationSkillFile) && !force) {
|
|
8339
8521
|
return {
|
|
8340
8522
|
message: `${slug} is already installed`
|
|
@@ -8350,7 +8532,7 @@ var ServiceCommands = class {
|
|
|
8350
8532
|
}
|
|
8351
8533
|
return null;
|
|
8352
8534
|
}
|
|
8353
|
-
mkdirSync5(
|
|
8535
|
+
mkdirSync5(join7(workspace, "skills"), { recursive: true });
|
|
8354
8536
|
cpSync2(dirname2(builtin.path), destination, { recursive: true, force: true });
|
|
8355
8537
|
return {
|
|
8356
8538
|
message: `Installed skill: ${slug}`
|
|
@@ -8412,7 +8594,7 @@ ${stderr}`.trim();
|
|
|
8412
8594
|
// src/cli/workspace.ts
|
|
8413
8595
|
import { cpSync as cpSync3, existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync9, readdirSync as readdirSync3, rmSync as rmSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
8414
8596
|
import { createRequire as createRequire2 } from "module";
|
|
8415
|
-
import { dirname as dirname3, join as
|
|
8597
|
+
import { dirname as dirname3, join as join8, resolve as resolve11 } from "path";
|
|
8416
8598
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
8417
8599
|
import { APP_NAME as APP_NAME4, getDataDir as getDataDir8 } from "@nextclaw/core";
|
|
8418
8600
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
@@ -8442,11 +8624,11 @@ var WorkspaceManager = class {
|
|
|
8442
8624
|
{ source: "memory/MEMORY.md", target: "memory/MEMORY.md" }
|
|
8443
8625
|
];
|
|
8444
8626
|
for (const entry of templateFiles) {
|
|
8445
|
-
const filePath =
|
|
8627
|
+
const filePath = join8(workspace, entry.target);
|
|
8446
8628
|
if (!force && existsSync11(filePath)) {
|
|
8447
8629
|
continue;
|
|
8448
8630
|
}
|
|
8449
|
-
const templatePath =
|
|
8631
|
+
const templatePath = join8(templateDir, entry.source);
|
|
8450
8632
|
if (!existsSync11(templatePath)) {
|
|
8451
8633
|
console.warn(`Warning: Template file missing: ${templatePath}`);
|
|
8452
8634
|
continue;
|
|
@@ -8457,15 +8639,15 @@ var WorkspaceManager = class {
|
|
|
8457
8639
|
writeFileSync5(filePath, content);
|
|
8458
8640
|
created.push(entry.target);
|
|
8459
8641
|
}
|
|
8460
|
-
const memoryDir =
|
|
8642
|
+
const memoryDir = join8(workspace, "memory");
|
|
8461
8643
|
if (!existsSync11(memoryDir)) {
|
|
8462
8644
|
mkdirSync6(memoryDir, { recursive: true });
|
|
8463
|
-
created.push(
|
|
8645
|
+
created.push(join8("memory", ""));
|
|
8464
8646
|
}
|
|
8465
|
-
const skillsDir =
|
|
8647
|
+
const skillsDir = join8(workspace, "skills");
|
|
8466
8648
|
if (!existsSync11(skillsDir)) {
|
|
8467
8649
|
mkdirSync6(skillsDir, { recursive: true });
|
|
8468
|
-
created.push(
|
|
8650
|
+
created.push(join8("skills", ""));
|
|
8469
8651
|
}
|
|
8470
8652
|
const seeded = this.seedBuiltinSkills(skillsDir, { force });
|
|
8471
8653
|
if (seeded > 0) {
|
|
@@ -8484,11 +8666,11 @@ var WorkspaceManager = class {
|
|
|
8484
8666
|
if (!entry.isDirectory()) {
|
|
8485
8667
|
continue;
|
|
8486
8668
|
}
|
|
8487
|
-
const src =
|
|
8488
|
-
if (!existsSync11(
|
|
8669
|
+
const src = join8(sourceDir, entry.name);
|
|
8670
|
+
if (!existsSync11(join8(src, "SKILL.md"))) {
|
|
8489
8671
|
continue;
|
|
8490
8672
|
}
|
|
8491
|
-
const dest =
|
|
8673
|
+
const dest = join8(targetDir, entry.name);
|
|
8492
8674
|
if (!force && existsSync11(dest)) {
|
|
8493
8675
|
continue;
|
|
8494
8676
|
}
|
|
@@ -8507,11 +8689,11 @@ var WorkspaceManager = class {
|
|
|
8507
8689
|
const require3 = createRequire2(import.meta.url);
|
|
8508
8690
|
const entry = require3.resolve("@nextclaw/core");
|
|
8509
8691
|
const pkgRoot = resolve11(dirname3(entry), "..");
|
|
8510
|
-
const distSkills =
|
|
8692
|
+
const distSkills = join8(pkgRoot, "dist", "skills");
|
|
8511
8693
|
if (existsSync11(distSkills)) {
|
|
8512
8694
|
return distSkills;
|
|
8513
8695
|
}
|
|
8514
|
-
const srcSkills =
|
|
8696
|
+
const srcSkills = join8(pkgRoot, "src", "agent", "skills");
|
|
8515
8697
|
if (existsSync11(srcSkills)) {
|
|
8516
8698
|
return srcSkills;
|
|
8517
8699
|
}
|
|
@@ -8527,7 +8709,7 @@ var WorkspaceManager = class {
|
|
|
8527
8709
|
}
|
|
8528
8710
|
const cliDir = resolve11(fileURLToPath4(new URL(".", import.meta.url)));
|
|
8529
8711
|
const pkgRoot = resolve11(cliDir, "..", "..");
|
|
8530
|
-
const candidates = [
|
|
8712
|
+
const candidates = [join8(pkgRoot, "templates")];
|
|
8531
8713
|
for (const candidate of candidates) {
|
|
8532
8714
|
if (existsSync11(candidate)) {
|
|
8533
8715
|
return candidate;
|
|
@@ -8536,8 +8718,8 @@ var WorkspaceManager = class {
|
|
|
8536
8718
|
return null;
|
|
8537
8719
|
}
|
|
8538
8720
|
getBridgeDir() {
|
|
8539
|
-
const userBridge =
|
|
8540
|
-
if (existsSync11(
|
|
8721
|
+
const userBridge = join8(getDataDir8(), "bridge");
|
|
8722
|
+
if (existsSync11(join8(userBridge, "dist", "index.js"))) {
|
|
8541
8723
|
return userBridge;
|
|
8542
8724
|
}
|
|
8543
8725
|
if (!which("npm")) {
|
|
@@ -8546,12 +8728,12 @@ var WorkspaceManager = class {
|
|
|
8546
8728
|
}
|
|
8547
8729
|
const cliDir = resolve11(fileURLToPath4(new URL(".", import.meta.url)));
|
|
8548
8730
|
const pkgRoot = resolve11(cliDir, "..", "..");
|
|
8549
|
-
const pkgBridge =
|
|
8550
|
-
const srcBridge =
|
|
8731
|
+
const pkgBridge = join8(pkgRoot, "bridge");
|
|
8732
|
+
const srcBridge = join8(pkgRoot, "..", "..", "bridge");
|
|
8551
8733
|
let source = null;
|
|
8552
|
-
if (existsSync11(
|
|
8734
|
+
if (existsSync11(join8(pkgBridge, "package.json"))) {
|
|
8553
8735
|
source = pkgBridge;
|
|
8554
|
-
} else if (existsSync11(
|
|
8736
|
+
} else if (existsSync11(join8(srcBridge, "package.json"))) {
|
|
8555
8737
|
source = srcBridge;
|
|
8556
8738
|
}
|
|
8557
8739
|
if (!source) {
|
|
@@ -8846,7 +9028,7 @@ var CliRuntime = class {
|
|
|
8846
9028
|
}
|
|
8847
9029
|
const config2 = loadConfig15();
|
|
8848
9030
|
const workspaceSetting = config2.agents.defaults.workspace;
|
|
8849
|
-
const workspacePath = !workspaceSetting || workspaceSetting === DEFAULT_WORKSPACE_PATH ?
|
|
9031
|
+
const workspacePath = !workspaceSetting || workspaceSetting === DEFAULT_WORKSPACE_PATH ? join9(getDataDir9(), DEFAULT_WORKSPACE_DIR) : expandHome2(workspaceSetting);
|
|
8850
9032
|
const workspaceExisted = existsSync12(workspacePath);
|
|
8851
9033
|
mkdirSync7(workspacePath, { recursive: true });
|
|
8852
9034
|
const templateResult = this.workspaceManager.createWorkspaceTemplates(
|
|
@@ -9039,7 +9221,7 @@ ${this.logo} ${APP_NAME5} is ready! (${source})`);
|
|
|
9039
9221
|
`${this.logo} Interactive mode (type exit or Ctrl+C to quit)
|
|
9040
9222
|
`
|
|
9041
9223
|
);
|
|
9042
|
-
const historyFile =
|
|
9224
|
+
const historyFile = join9(getDataDir9(), "history", "cli_history");
|
|
9043
9225
|
const historyDir = resolve12(historyFile, "..");
|
|
9044
9226
|
mkdirSync7(historyDir, { recursive: true });
|
|
9045
9227
|
const history = existsSync12(historyFile) ? readFileSync10(historyFile, "utf-8").split("\n").filter(Boolean) : [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nextclaw",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.11",
|
|
4
4
|
"description": "Lightweight personal AI assistant with CLI, multi-provider routing, and channel integrations.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -35,20 +35,30 @@
|
|
|
35
35
|
"ui-dist",
|
|
36
36
|
"templates"
|
|
37
37
|
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"dev": "tsx watch --tsconfig tsconfig.json src/cli/index.ts",
|
|
40
|
+
"dev:build": "tsx src/cli/index.ts",
|
|
41
|
+
"build": "node scripts/sync-usage-template.mjs && tsup src/index.ts src/cli/index.ts --format esm --dts --out-dir dist && node scripts/copy-ui-dist.mjs",
|
|
42
|
+
"prepack": "pnpm run build",
|
|
43
|
+
"start": "node dist/cli.js",
|
|
44
|
+
"lint": "eslint .",
|
|
45
|
+
"tsc": "tsc -p tsconfig.json",
|
|
46
|
+
"test": "vitest"
|
|
47
|
+
},
|
|
38
48
|
"dependencies": {
|
|
39
49
|
"chokidar": "^3.6.0",
|
|
40
50
|
"commander": "^12.1.0",
|
|
41
51
|
"yaml": "^2.8.1",
|
|
42
|
-
"@nextclaw/core": "
|
|
43
|
-
"@nextclaw/mcp": "
|
|
44
|
-
"@nextclaw/ncp": "
|
|
45
|
-
"@nextclaw/ncp-agent-runtime": "
|
|
46
|
-
"@nextclaw/ncp-mcp": "
|
|
47
|
-
"@nextclaw/ncp-toolkit": "
|
|
48
|
-
"@nextclaw/
|
|
49
|
-
"@nextclaw/
|
|
50
|
-
"@nextclaw/
|
|
51
|
-
"@nextclaw/
|
|
52
|
+
"@nextclaw/core": "workspace:*",
|
|
53
|
+
"@nextclaw/mcp": "workspace:*",
|
|
54
|
+
"@nextclaw/ncp": "workspace:*",
|
|
55
|
+
"@nextclaw/ncp-agent-runtime": "workspace:*",
|
|
56
|
+
"@nextclaw/ncp-mcp": "workspace:*",
|
|
57
|
+
"@nextclaw/ncp-toolkit": "workspace:*",
|
|
58
|
+
"@nextclaw/remote": "workspace:*",
|
|
59
|
+
"@nextclaw/runtime": "workspace:*",
|
|
60
|
+
"@nextclaw/server": "workspace:*",
|
|
61
|
+
"@nextclaw/openclaw-compat": "workspace:*"
|
|
52
62
|
},
|
|
53
63
|
"devDependencies": {
|
|
54
64
|
"@types/node": "^20.17.6",
|
|
@@ -57,14 +67,5 @@
|
|
|
57
67
|
"tsx": "^4.19.2",
|
|
58
68
|
"typescript": "^5.6.3",
|
|
59
69
|
"vitest": "^2.1.2"
|
|
60
|
-
},
|
|
61
|
-
"scripts": {
|
|
62
|
-
"dev": "tsx watch --tsconfig tsconfig.json src/cli/index.ts",
|
|
63
|
-
"dev:build": "tsx src/cli/index.ts",
|
|
64
|
-
"build": "node scripts/sync-usage-template.mjs && tsup src/index.ts src/cli/index.ts --format esm --dts --out-dir dist && node scripts/copy-ui-dist.mjs",
|
|
65
|
-
"start": "node dist/cli.js",
|
|
66
|
-
"lint": "eslint .",
|
|
67
|
-
"tsc": "tsc -p tsconfig.json",
|
|
68
|
-
"test": "vitest"
|
|
69
70
|
}
|
|
70
|
-
}
|
|
71
|
+
}
|