nextclaw 0.13.0 → 0.13.2

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 +235 -140
  2. package/package.json +7 -7
package/dist/cli/index.js CHANGED
@@ -6,9 +6,9 @@ import { APP_NAME as APP_NAME5, APP_TAGLINE } from "@nextclaw/core";
6
6
 
7
7
  // src/cli/runtime.ts
8
8
  import {
9
- loadConfig as loadConfig12,
10
- saveConfig as saveConfig8,
11
- getConfigPath as getConfigPath5,
9
+ loadConfig as loadConfig13,
10
+ saveConfig as saveConfig9,
11
+ getConfigPath as getConfigPath6,
12
12
  getDataDir as getDataDir9,
13
13
  ConfigSchema as ConfigSchema2,
14
14
  getWorkspacePath as getWorkspacePath10,
@@ -28,7 +28,7 @@ import {
28
28
  } from "@nextclaw/openclaw-compat";
29
29
  import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
30
30
  import { join as join9, resolve as resolve12 } from "path";
31
- import { createInterface as createInterface2 } from "readline";
31
+ import { createInterface as createInterface3 } from "readline";
32
32
  import { fileURLToPath as fileURLToPath4 } from "url";
33
33
  import { spawn as spawn3 } from "child_process";
34
34
 
@@ -1440,27 +1440,7 @@ async function installPluginMutation(pathOrSpec, opts = {}) {
1440
1440
  };
1441
1441
  }
1442
1442
 
1443
- // src/cli/commands/plugins.ts
1444
- function loadPluginRegistry(config2, workspaceDir) {
1445
- const workspaceExtensionsDir = process.env.NEXTCLAW_DEV_FIRST_PARTY_PLUGIN_DIR;
1446
- const configWithDevPluginPaths = applyDevFirstPartyPluginLoadPaths(
1447
- config2,
1448
- workspaceExtensionsDir
1449
- );
1450
- const excludedRoots = resolveDevFirstPartyPluginInstallRoots(config2, workspaceExtensionsDir);
1451
- return loadOpenClawPlugins({
1452
- config: configWithDevPluginPaths,
1453
- workspaceDir,
1454
- excludeRoots: excludedRoots,
1455
- ...buildReservedPluginLoadOptions(),
1456
- logger: {
1457
- info: (message) => console.log(message),
1458
- warn: (message) => console.warn(message),
1459
- error: (message) => console.error(message),
1460
- debug: (message) => console.debug(message)
1461
- }
1462
- });
1463
- }
1443
+ // src/cli/commands/plugin-extension-registry.ts
1464
1444
  function toExtensionRegistry(pluginRegistry) {
1465
1445
  return {
1466
1446
  tools: pluginRegistry.tools.map((tool) => ({
@@ -1497,6 +1477,28 @@ function toExtensionRegistry(pluginRegistry) {
1497
1477
  }))
1498
1478
  };
1499
1479
  }
1480
+
1481
+ // src/cli/commands/plugins.ts
1482
+ function loadPluginRegistry(config2, workspaceDir) {
1483
+ const workspaceExtensionsDir = process.env.NEXTCLAW_DEV_FIRST_PARTY_PLUGIN_DIR;
1484
+ const configWithDevPluginPaths = applyDevFirstPartyPluginLoadPaths(
1485
+ config2,
1486
+ workspaceExtensionsDir
1487
+ );
1488
+ const excludedRoots = resolveDevFirstPartyPluginInstallRoots(config2, workspaceExtensionsDir);
1489
+ return loadOpenClawPlugins({
1490
+ config: configWithDevPluginPaths,
1491
+ workspaceDir,
1492
+ excludeRoots: excludedRoots,
1493
+ ...buildReservedPluginLoadOptions(),
1494
+ logger: {
1495
+ info: (message) => console.log(message),
1496
+ warn: (message) => console.warn(message),
1497
+ error: (message) => console.error(message),
1498
+ debug: (message) => console.debug(message)
1499
+ }
1500
+ });
1501
+ }
1500
1502
  function logPluginDiagnostics(registry) {
1501
1503
  for (const diag of registry.diagnostics) {
1502
1504
  const prefix = diag.pluginId ? `${diag.pluginId}: ` : "";
@@ -2859,8 +2861,162 @@ var CronCommands = class {
2859
2861
  }
2860
2862
  };
2861
2863
 
2864
+ // src/cli/commands/platform-auth.ts
2865
+ import { getConfigPath as getConfigPath2, loadConfig as loadConfig7, saveConfig as saveConfig6 } from "@nextclaw/core";
2866
+ import { createInterface as createInterface2 } from "readline";
2867
+
2868
+ // src/cli/commands/platform-api-base.ts
2869
+ var DEFAULT_PLATFORM_API_BASE = "https://ai-gateway-api.nextclaw.io/v1";
2870
+ var INVALID_PLATFORM_HINT = `Use ${DEFAULT_PLATFORM_API_BASE} or the platform root URL without a trailing path.`;
2871
+ function trimTrailingSlash(value) {
2872
+ return value.replace(/\/+$/, "");
2873
+ }
2874
+ function normalizeExplicitApiBase(rawApiBase) {
2875
+ const trimmed = trimTrailingSlash(rawApiBase.trim());
2876
+ if (!trimmed) {
2877
+ return "";
2878
+ }
2879
+ return trimmed.replace(/\/v1?$/i, "");
2880
+ }
2881
+ function resolvePlatformApiBase(params) {
2882
+ const explicitApiBase = typeof params.explicitApiBase === "string" ? params.explicitApiBase.trim() : "";
2883
+ const configuredApiBase = typeof params.configuredApiBase === "string" ? params.configuredApiBase.trim() : "";
2884
+ const fallbackApiBase = params.fallbackApiBase ?? DEFAULT_PLATFORM_API_BASE;
2885
+ const inputApiBase = explicitApiBase || configuredApiBase || (params.requireConfigured ? "" : fallbackApiBase);
2886
+ if (!inputApiBase) {
2887
+ throw new Error("Platform API base is missing. Pass --api-base or run nextclaw login.");
2888
+ }
2889
+ const platformBase = normalizeExplicitApiBase(inputApiBase);
2890
+ if (!platformBase) {
2891
+ throw new Error(`Invalid --api-base "${inputApiBase}". ${INVALID_PLATFORM_HINT}`);
2892
+ }
2893
+ let parsedUrl;
2894
+ try {
2895
+ parsedUrl = new URL(platformBase);
2896
+ } catch {
2897
+ throw new Error(`Invalid --api-base "${inputApiBase}". ${INVALID_PLATFORM_HINT}`);
2898
+ }
2899
+ if (parsedUrl.pathname !== "" && parsedUrl.pathname !== "/") {
2900
+ throw new Error(`Invalid --api-base "${inputApiBase}". ${INVALID_PLATFORM_HINT}`);
2901
+ }
2902
+ const normalizedPlatformBase = trimTrailingSlash(parsedUrl.toString());
2903
+ return {
2904
+ platformBase: normalizedPlatformBase,
2905
+ v1Base: `${normalizedPlatformBase}/v1`,
2906
+ inputApiBase
2907
+ };
2908
+ }
2909
+ function buildPlatformApiBaseErrorMessage(inputApiBase, rawMessage) {
2910
+ if (rawMessage.includes("Remote session cookie missing") || rawMessage.includes("endpoint not found") || rawMessage.includes("NOT_FOUND")) {
2911
+ return `Invalid --api-base "${inputApiBase}". ${INVALID_PLATFORM_HINT}`;
2912
+ }
2913
+ return rawMessage;
2914
+ }
2915
+
2916
+ // src/cli/commands/platform-auth.ts
2917
+ function resolveProviderConfig(opts) {
2918
+ const configPath = getConfigPath2();
2919
+ const config2 = loadConfig7(configPath);
2920
+ const providers = config2.providers;
2921
+ const nextclawProvider = providers.nextclaw ?? {
2922
+ displayName: "",
2923
+ apiKey: "",
2924
+ apiBase: null,
2925
+ extraHeaders: null,
2926
+ wireApi: "auto",
2927
+ models: []
2928
+ };
2929
+ const configuredApiBase = typeof nextclawProvider.apiBase === "string" && nextclawProvider.apiBase.trim().length > 0 ? nextclawProvider.apiBase.trim() : "https://ai-gateway-api.nextclaw.io/v1";
2930
+ const requestedApiBase = typeof opts.apiBase === "string" && opts.apiBase.trim().length > 0 ? opts.apiBase.trim() : configuredApiBase;
2931
+ const { platformBase, v1Base, inputApiBase } = resolvePlatformApiBase({
2932
+ explicitApiBase: requestedApiBase,
2933
+ fallbackApiBase: "https://ai-gateway-api.nextclaw.io/v1"
2934
+ });
2935
+ return {
2936
+ configPath,
2937
+ config: config2,
2938
+ providers,
2939
+ nextclawProvider,
2940
+ platformBase,
2941
+ v1Base,
2942
+ inputApiBase
2943
+ };
2944
+ }
2945
+ async function resolveCredentials(opts) {
2946
+ let email = typeof opts.email === "string" ? opts.email.trim() : "";
2947
+ let password = typeof opts.password === "string" ? opts.password : "";
2948
+ if (email && password) {
2949
+ return { email, password };
2950
+ }
2951
+ const rl = createInterface2({
2952
+ input: process.stdin,
2953
+ output: process.stdout
2954
+ });
2955
+ try {
2956
+ if (!email) {
2957
+ email = (await prompt(rl, "Email: ")).trim();
2958
+ }
2959
+ if (!password) {
2960
+ password = await prompt(rl, "Password: ");
2961
+ }
2962
+ } finally {
2963
+ rl.close();
2964
+ }
2965
+ if (!email || !password) {
2966
+ throw new Error("Email and password are required.");
2967
+ }
2968
+ return { email, password };
2969
+ }
2970
+ function readLoginPayload(raw) {
2971
+ let parsed = null;
2972
+ try {
2973
+ parsed = JSON.parse(raw);
2974
+ } catch {
2975
+ parsed = null;
2976
+ }
2977
+ const token = typeof parsed === "object" && parsed && "data" in parsed && typeof parsed.data?.token === "string" ? parsed.data.token : "";
2978
+ const role = typeof parsed === "object" && parsed && "data" in parsed && typeof parsed.data?.user?.role === "string" ? parsed.data.user.role : "user";
2979
+ if (!token) {
2980
+ throw new Error("Login succeeded but token is missing.");
2981
+ }
2982
+ return { token, role };
2983
+ }
2984
+ var PlatformAuthCommands = class {
2985
+ async login(opts = {}) {
2986
+ const { configPath, config: config2, providers, nextclawProvider, platformBase, v1Base, inputApiBase } = resolveProviderConfig(opts);
2987
+ const { email, password } = await resolveCredentials(opts);
2988
+ const endpoint = opts.register ? `${platformBase}/platform/auth/register` : `${platformBase}/platform/auth/login`;
2989
+ const response = await fetch(endpoint, {
2990
+ method: "POST",
2991
+ headers: {
2992
+ "Content-Type": "application/json"
2993
+ },
2994
+ body: JSON.stringify({ email, password })
2995
+ });
2996
+ const raw = await response.text();
2997
+ if (!response.ok) {
2998
+ let parsed = null;
2999
+ try {
3000
+ parsed = JSON.parse(raw);
3001
+ } catch {
3002
+ parsed = null;
3003
+ }
3004
+ const maybeMessage = typeof parsed === "object" && parsed && "error" in parsed && typeof parsed.error?.message === "string" ? parsed.error.message : raw || `Request failed (${response.status})`;
3005
+ throw new Error(buildPlatformApiBaseErrorMessage(inputApiBase, maybeMessage));
3006
+ }
3007
+ const { token, role } = readLoginPayload(raw);
3008
+ nextclawProvider.apiBase = v1Base;
3009
+ nextclawProvider.apiKey = token;
3010
+ providers.nextclaw = nextclawProvider;
3011
+ saveConfig6(config2, configPath);
3012
+ console.log(`\u2713 Logged in to NextClaw platform (${platformBase})`);
3013
+ console.log(`\u2713 Account: ${email} (${role})`);
3014
+ console.log(`\u2713 Token saved into providers.nextclaw.apiKey`);
3015
+ }
3016
+ };
3017
+
2862
3018
  // src/cli/commands/remote.ts
2863
- import { getConfigPath as getConfigPath2, getDataDir as getDataDir4, loadConfig as loadConfig7 } from "@nextclaw/core";
3019
+ import { getConfigPath as getConfigPath3, getDataDir as getDataDir4, loadConfig as loadConfig8 } from "@nextclaw/core";
2864
3020
  import { ensureUiBridgeSecret } from "@nextclaw/server";
2865
3021
  import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
2866
3022
  import { dirname as dirname2, join as join4 } from "path";
@@ -2909,7 +3065,7 @@ var RemoteCommands = class {
2909
3065
  return deviceInstallId;
2910
3066
  }
2911
3067
  resolvePlatformAccess(opts) {
2912
- const config2 = loadConfig7(getConfigPath2());
3068
+ const config2 = loadConfig8(getConfigPath3());
2913
3069
  const providers = config2.providers;
2914
3070
  const nextclawProvider = providers.nextclaw;
2915
3071
  const token = typeof nextclawProvider?.apiKey === "string" ? nextclawProvider.apiKey.trim() : "";
@@ -2921,7 +3077,10 @@ var RemoteCommands = class {
2921
3077
  if (!rawApiBase) {
2922
3078
  throw new Error("Platform API base is missing. Pass --api-base or run nextclaw login.");
2923
3079
  }
2924
- const platformBase = rawApiBase.replace(/\/v1\/?$/i, "");
3080
+ const { platformBase } = resolvePlatformApiBase({
3081
+ explicitApiBase: rawApiBase,
3082
+ requireConfigured: true
3083
+ });
2925
3084
  return { platformBase, token, config: config2 };
2926
3085
  }
2927
3086
  resolveLocalOrigin(config2, opts) {
@@ -3129,11 +3288,11 @@ import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
3129
3288
  import { resolve as resolve8 } from "path";
3130
3289
  import {
3131
3290
  APP_NAME,
3132
- getConfigPath as getConfigPath3,
3291
+ getConfigPath as getConfigPath4,
3133
3292
  getDataDir as getDataDir5,
3134
3293
  getWorkspacePath as getWorkspacePath4,
3135
3294
  hasSecretRef,
3136
- loadConfig as loadConfig8
3295
+ loadConfig as loadConfig9
3137
3296
  } from "@nextclaw/core";
3138
3297
  import { listBuiltinProviders } from "@nextclaw/runtime";
3139
3298
  var DiagnosticsCommands = class {
@@ -3294,8 +3453,8 @@ var DiagnosticsCommands = class {
3294
3453
  process.exitCode = exitCode;
3295
3454
  }
3296
3455
  async collectRuntimeStatus(params) {
3297
- const configPath = getConfigPath3();
3298
- const config2 = loadConfig8();
3456
+ const configPath = getConfigPath4();
3457
+ const config2 = loadConfig9();
3299
3458
  const workspacePath = getWorkspacePath4(config2.agents.defaults.workspace);
3300
3459
  const serviceStatePath = resolve8(getDataDir5(), "run", "service.json");
3301
3460
  const fixActions = [];
@@ -3492,8 +3651,8 @@ import {
3492
3651
  redactConfigObject
3493
3652
  } from "@nextclaw/core";
3494
3653
  var hashRaw = (raw) => createHash("sha256").update(raw).digest("hex");
3495
- var readConfigSnapshot = (getConfigPath6) => {
3496
- const path2 = getConfigPath6();
3654
+ var readConfigSnapshot = (getConfigPath7) => {
3655
+ const path2 = getConfigPath7();
3497
3656
  let raw = "";
3498
3657
  let parsed = {};
3499
3658
  if (existsSync8(path2)) {
@@ -3954,7 +4113,7 @@ var MissingProvider = class extends LLMProvider {
3954
4113
  };
3955
4114
 
3956
4115
  // src/cli/commands/service-marketplace-installer.ts
3957
- import { getWorkspacePath as getWorkspacePath5, loadConfig as loadConfig10 } from "@nextclaw/core";
4116
+ import { getWorkspacePath as getWorkspacePath5, loadConfig as loadConfig11 } from "@nextclaw/core";
3958
4117
  import { existsSync as existsSync9, rmSync as rmSync4 } from "fs";
3959
4118
  import { join as join5 } from "path";
3960
4119
 
@@ -4004,7 +4163,7 @@ var buildMarketplaceSkillInstallArgs = (params) => {
4004
4163
  };
4005
4164
 
4006
4165
  // src/cli/commands/service-mcp-marketplace-ops.ts
4007
- import { loadConfig as loadConfig9, saveConfig as saveConfig6 } from "@nextclaw/core";
4166
+ import { loadConfig as loadConfig10, saveConfig as saveConfig7 } from "@nextclaw/core";
4008
4167
  import { McpDoctorFacade as McpDoctorFacade2, McpMutationService as McpMutationService2 } from "@nextclaw/mcp";
4009
4168
  var ServiceMcpMarketplaceOps = class {
4010
4169
  constructor(options) {
@@ -4072,13 +4231,13 @@ var ServiceMcpMarketplaceOps = class {
4072
4231
  }
4073
4232
  createMutationService() {
4074
4233
  return new McpMutationService2({
4075
- getConfig: () => loadConfig9(),
4076
- saveConfig: (config2) => saveConfig6(config2)
4234
+ getConfig: () => loadConfig10(),
4235
+ saveConfig: (config2) => saveConfig7(config2)
4077
4236
  });
4078
4237
  }
4079
4238
  createDoctorFacade() {
4080
4239
  return new McpDoctorFacade2({
4081
- getConfig: () => loadConfig9()
4240
+ getConfig: () => loadConfig10()
4082
4241
  });
4083
4242
  }
4084
4243
  };
@@ -4119,7 +4278,7 @@ var ServiceMarketplaceInstaller = class {
4119
4278
  if (params.kind && params.kind !== "marketplace") {
4120
4279
  throw new Error(`Unsupported marketplace skill kind: ${params.kind}`);
4121
4280
  }
4122
- const workspace = getWorkspacePath5(loadConfig10().agents.defaults.workspace);
4281
+ const workspace = getWorkspacePath5(loadConfig11().agents.defaults.workspace);
4123
4282
  const args = buildMarketplaceSkillInstallArgs({
4124
4283
  slug: params.slug,
4125
4284
  workspace,
@@ -4158,7 +4317,7 @@ var ServiceMarketplaceInstaller = class {
4158
4317
  return { message: result.message };
4159
4318
  }
4160
4319
  async uninstallSkill(slug) {
4161
- const workspace = getWorkspacePath5(loadConfig10().agents.defaults.workspace);
4320
+ const workspace = getWorkspacePath5(loadConfig11().agents.defaults.workspace);
4162
4321
  const targetDir = join5(workspace, "skills", slug);
4163
4322
  if (!existsSync9(targetDir)) {
4164
4323
  throw new Error(`Skill not installed in workspace: ${slug}`);
@@ -6744,18 +6903,18 @@ var {
6744
6903
  ChannelManager: ChannelManager2,
6745
6904
  CronService: CronService2,
6746
6905
  getApiBase,
6747
- getConfigPath: getConfigPath4,
6906
+ getConfigPath: getConfigPath5,
6748
6907
  getDataDir: getDataDir7,
6749
6908
  getProvider,
6750
6909
  getProviderName,
6751
6910
  getWorkspacePath: getWorkspacePath9,
6752
6911
  HeartbeatService,
6753
6912
  LiteLLMProvider,
6754
- loadConfig: loadConfig11,
6913
+ loadConfig: loadConfig12,
6755
6914
  MessageBus,
6756
6915
  ProviderManager,
6757
6916
  resolveConfigSecrets: resolveConfigSecrets2,
6758
- saveConfig: saveConfig7,
6917
+ saveConfig: saveConfig8,
6759
6918
  SessionManager,
6760
6919
  parseAgentScopedSessionKey: parseAgentScopedSessionKey3
6761
6920
  } = NextclawCore;
@@ -6775,8 +6934,8 @@ var ServiceCommands = class {
6775
6934
  async startGateway(options = {}) {
6776
6935
  this.applyLiveConfigReload = null;
6777
6936
  this.liveUiNcpAgent = null;
6778
- const runtimeConfigPath = getConfigPath4();
6779
- const config2 = resolveConfigSecrets2(loadConfig11(), { configPath: runtimeConfigPath });
6937
+ const runtimeConfigPath = getConfigPath5();
6938
+ const config2 = resolveConfigSecrets2(loadConfig12(), { configPath: runtimeConfigPath });
6780
6939
  const workspace = getWorkspacePath9(config2.agents.defaults.workspace);
6781
6940
  let pluginRegistry = loadPluginRegistry(config2, workspace);
6782
6941
  let extensionRegistry = toExtensionRegistry(pluginRegistry);
@@ -6821,7 +6980,7 @@ var ServiceCommands = class {
6821
6980
  sessionManager,
6822
6981
  providerManager,
6823
6982
  makeProvider: (nextConfig) => this.makeProvider(nextConfig, { allowMissing: true }) ?? this.makeMissingProvider(nextConfig),
6824
- loadConfig: () => resolveConfigSecrets2(loadConfig11(), { configPath: runtimeConfigPath }),
6983
+ loadConfig: () => resolveConfigSecrets2(loadConfig12(), { configPath: runtimeConfigPath }),
6825
6984
  getExtensionChannels: () => extensionRegistry.channels,
6826
6985
  onRestartRequired: (paths) => {
6827
6986
  void this.deps.requestRestart({
@@ -6832,14 +6991,14 @@ var ServiceCommands = class {
6832
6991
  }
6833
6992
  });
6834
6993
  this.applyLiveConfigReload = async () => {
6835
- await reloader.applyReloadPlan(resolveConfigSecrets2(loadConfig11(), { configPath: runtimeConfigPath }));
6994
+ await reloader.applyReloadPlan(resolveConfigSecrets2(loadConfig12(), { configPath: runtimeConfigPath }));
6836
6995
  };
6837
6996
  const gatewayController = new GatewayControllerImpl({
6838
6997
  reloader,
6839
6998
  cron: cron2,
6840
6999
  sessionManager,
6841
- getConfigPath: getConfigPath4,
6842
- saveConfig: saveConfig7,
7000
+ getConfigPath: getConfigPath5,
7001
+ saveConfig: saveConfig8,
6843
7002
  requestRestart: async (options2) => {
6844
7003
  await this.deps.requestRestart({
6845
7004
  reason: options2?.reason ?? "gateway tool restart",
@@ -6865,7 +7024,7 @@ var ServiceCommands = class {
6865
7024
  resolveMessageToolHints: ({ channel, accountId }) => resolvePluginChannelMessageToolHints({
6866
7025
  registry: pluginRegistry,
6867
7026
  channel,
6868
- cfg: resolveConfigSecrets2(loadConfig11(), { configPath: runtimeConfigPath }),
7027
+ cfg: resolveConfigSecrets2(loadConfig12(), { configPath: runtimeConfigPath }),
6869
7028
  accountId
6870
7029
  })
6871
7030
  });
@@ -6898,14 +7057,14 @@ var ServiceCommands = class {
6898
7057
  });
6899
7058
  let pluginChannelBindings = getPluginChannelBindings3(pluginRegistry);
6900
7059
  setPluginRuntimeBridge({
6901
- loadConfig: () => toPluginConfigView(resolveConfigSecrets2(loadConfig11(), { configPath: runtimeConfigPath }), pluginChannelBindings),
7060
+ loadConfig: () => toPluginConfigView(resolveConfigSecrets2(loadConfig12(), { configPath: runtimeConfigPath }), pluginChannelBindings),
6902
7061
  writeConfigFile: async (nextConfigView) => {
6903
7062
  if (!nextConfigView || typeof nextConfigView !== "object" || Array.isArray(nextConfigView)) {
6904
7063
  throw new Error("plugin runtime writeConfigFile expects an object config");
6905
7064
  }
6906
- const current = loadConfig11();
7065
+ const current = loadConfig12();
6907
7066
  const next = mergePluginConfigView(current, nextConfigView, pluginChannelBindings);
6908
- saveConfig7(next);
7067
+ saveConfig8(next);
6909
7068
  },
6910
7069
  dispatchReplyWithBufferedBlockDispatcher: async ({ ctx, dispatcherOptions }) => {
6911
7070
  const bodyForAgent = typeof ctx.BodyForAgent === "string" ? ctx.BodyForAgent : "";
@@ -6979,12 +7138,12 @@ var ServiceCommands = class {
6979
7138
  providerManager,
6980
7139
  bus,
6981
7140
  gatewayController,
6982
- () => resolveConfigSecrets2(loadConfig11(), { configPath: runtimeConfigPath }),
7141
+ () => resolveConfigSecrets2(loadConfig12(), { configPath: runtimeConfigPath }),
6983
7142
  () => extensionRegistry,
6984
7143
  ({ channel, accountId }) => resolvePluginChannelMessageToolHints({
6985
7144
  registry: pluginRegistry,
6986
7145
  channel,
6987
- cfg: resolveConfigSecrets2(loadConfig11(), { configPath: runtimeConfigPath }),
7146
+ cfg: resolveConfigSecrets2(loadConfig12(), { configPath: runtimeConfigPath }),
6988
7147
  accountId
6989
7148
  })
6990
7149
  );
@@ -7021,7 +7180,7 @@ var ServiceCommands = class {
7021
7180
  return trimmed || void 0;
7022
7181
  }
7023
7182
  watchConfigFile(reloader) {
7024
- const configPath = resolve10(getConfigPath4());
7183
+ const configPath = resolve10(getConfigPath5());
7025
7184
  const watcher = chokidar.watch(configPath, {
7026
7185
  ignoreInitial: true,
7027
7186
  awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 }
@@ -7142,7 +7301,7 @@ var ServiceCommands = class {
7142
7301
  });
7143
7302
  }
7144
7303
  async runForeground(options) {
7145
- const config2 = loadConfig11();
7304
+ const config2 = loadConfig12();
7146
7305
  const uiConfig = resolveUiConfig(config2, options.uiOverrides);
7147
7306
  const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
7148
7307
  if (options.open) {
@@ -7155,7 +7314,7 @@ var ServiceCommands = class {
7155
7314
  });
7156
7315
  }
7157
7316
  async startService(options) {
7158
- const config2 = loadConfig11();
7317
+ const config2 = loadConfig12();
7159
7318
  const uiConfig = resolveUiConfig(config2, options.uiOverrides);
7160
7319
  const uiUrl = resolveUiApiBase(uiConfig.host, uiConfig.port);
7161
7320
  const apiUrl = `${uiUrl}/api`;
@@ -7569,7 +7728,7 @@ var ServiceCommands = class {
7569
7728
  return null;
7570
7729
  }
7571
7730
  console.error("Error: No API key configured.");
7572
- console.error(`Set one in ${getConfigPath4()} under providers section`);
7731
+ console.error(`Set one in ${getConfigPath5()} under providers section`);
7573
7732
  process.exit(1);
7574
7733
  }
7575
7734
  return new LiteLLMProvider({
@@ -7696,7 +7855,7 @@ var ServiceCommands = class {
7696
7855
  const uiServer = startUiServer({
7697
7856
  host: uiConfig.host,
7698
7857
  port: uiConfig.port,
7699
- configPath: getConfigPath4(),
7858
+ configPath: getConfigPath5(),
7700
7859
  productVersion: getPackageVersion(),
7701
7860
  staticDir: uiStaticDir ?? void 0,
7702
7861
  cronService,
@@ -7784,7 +7943,7 @@ var ServiceCommands = class {
7784
7943
  }
7785
7944
  }
7786
7945
  installBuiltinMarketplaceSkill(slug, force) {
7787
- const workspace = getWorkspacePath9(loadConfig11().agents.defaults.workspace);
7946
+ const workspace = getWorkspacePath9(loadConfig12().agents.defaults.workspace);
7788
7947
  const destination = join7(workspace, "skills", slug);
7789
7948
  const destinationSkillFile = join7(destination, "SKILL.md");
7790
7949
  if (existsSync11(destinationSkillFile) && !force) {
@@ -8063,6 +8222,7 @@ var CliRuntime = class {
8063
8222
  pluginCommands;
8064
8223
  channelCommands;
8065
8224
  cronCommands;
8225
+ platformAuthCommands;
8066
8226
  remoteCommands;
8067
8227
  diagnosticsCommands;
8068
8228
  constructor(options = {}) {
@@ -8085,6 +8245,7 @@ var CliRuntime = class {
8085
8245
  requestRestart: (params) => this.requestRestart(params)
8086
8246
  });
8087
8247
  this.cronCommands = new CronCommands();
8248
+ this.platformAuthCommands = new PlatformAuthCommands();
8088
8249
  this.remoteCommands = new RemoteCommands();
8089
8250
  this.diagnosticsCommands = new DiagnosticsCommands({ logo: this.logo });
8090
8251
  this.restartCoordinator = new RestartCoordinator({
@@ -8279,14 +8440,14 @@ var CliRuntime = class {
8279
8440
  const source = options.source ?? "init";
8280
8441
  const prefix = options.auto ? "Auto init" : "Init";
8281
8442
  const force = Boolean(options.force);
8282
- const configPath = getConfigPath5();
8443
+ const configPath = getConfigPath6();
8283
8444
  let createdConfig = false;
8284
8445
  if (!existsSync13(configPath)) {
8285
8446
  const config3 = ConfigSchema2.parse({});
8286
- saveConfig8(config3);
8447
+ saveConfig9(config3);
8287
8448
  createdConfig = true;
8288
8449
  }
8289
- const config2 = loadConfig12();
8450
+ const config2 = loadConfig13();
8290
8451
  const workspaceSetting = config2.agents.defaults.workspace;
8291
8452
  const workspacePath = !workspaceSetting || workspaceSetting === DEFAULT_WORKSPACE_PATH ? join9(getDataDir9(), DEFAULT_WORKSPACE_DIR) : expandHome2(workspaceSetting);
8292
8453
  const workspaceExisted = existsSync13(workspacePath);
@@ -8321,73 +8482,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
8321
8482
  }
8322
8483
  async login(opts = {}) {
8323
8484
  await this.init({ source: "login", auto: true });
8324
- const configPath = getConfigPath5();
8325
- const config2 = loadConfig12(configPath);
8326
- const providers = config2.providers;
8327
- const nextclawProvider = providers.nextclaw ?? {
8328
- displayName: "",
8329
- apiKey: "",
8330
- apiBase: null,
8331
- extraHeaders: null,
8332
- wireApi: "auto",
8333
- models: []
8334
- };
8335
- const configuredApiBase = typeof nextclawProvider.apiBase === "string" && nextclawProvider.apiBase.trim().length > 0 ? nextclawProvider.apiBase.trim() : "https://ai-gateway-api.nextclaw.io/v1";
8336
- const requestedApiBase = typeof opts.apiBase === "string" && opts.apiBase.trim().length > 0 ? opts.apiBase.trim() : configuredApiBase;
8337
- const platformBase = requestedApiBase.replace(/\/v1\/?$/i, "");
8338
- const v1Base = `${platformBase}/v1`;
8339
- let email = typeof opts.email === "string" ? opts.email.trim() : "";
8340
- let password = typeof opts.password === "string" ? opts.password : "";
8341
- if (!email || !password) {
8342
- const rl = createInterface2({
8343
- input: process.stdin,
8344
- output: process.stdout
8345
- });
8346
- try {
8347
- if (!email) {
8348
- email = (await prompt(rl, "Email: ")).trim();
8349
- }
8350
- if (!password) {
8351
- password = await prompt(rl, "Password: ");
8352
- }
8353
- } finally {
8354
- rl.close();
8355
- }
8356
- }
8357
- if (!email || !password) {
8358
- throw new Error("Email and password are required.");
8359
- }
8360
- const endpoint = opts.register ? `${platformBase}/platform/auth/register` : `${platformBase}/platform/auth/login`;
8361
- const response = await fetch(endpoint, {
8362
- method: "POST",
8363
- headers: {
8364
- "Content-Type": "application/json"
8365
- },
8366
- body: JSON.stringify({ email, password })
8367
- });
8368
- const raw = await response.text();
8369
- let parsed = null;
8370
- try {
8371
- parsed = JSON.parse(raw);
8372
- } catch {
8373
- parsed = null;
8374
- }
8375
- if (!response.ok) {
8376
- const maybeMessage = typeof parsed === "object" && parsed && "error" in parsed && typeof parsed.error?.message === "string" ? parsed.error.message : raw || `Request failed (${response.status})`;
8377
- throw new Error(maybeMessage);
8378
- }
8379
- const token = typeof parsed === "object" && parsed && "data" in parsed && typeof parsed.data?.token === "string" ? parsed.data.token : "";
8380
- const role = typeof parsed === "object" && parsed && "data" in parsed && typeof parsed.data?.user?.role === "string" ? parsed.data.user.role : "user";
8381
- if (!token) {
8382
- throw new Error("Login succeeded but token is missing.");
8383
- }
8384
- nextclawProvider.apiBase = v1Base;
8385
- nextclawProvider.apiKey = token;
8386
- providers.nextclaw = nextclawProvider;
8387
- saveConfig8(config2, configPath);
8388
- console.log(`\u2713 Logged in to NextClaw platform (${platformBase})`);
8389
- console.log(`\u2713 Account: ${email} (${role})`);
8390
- console.log(`\u2713 Token saved into providers.nextclaw.apiKey`);
8485
+ await this.platformAuthCommands.login(opts);
8391
8486
  }
8392
8487
  async remoteConnect(opts = {}) {
8393
8488
  await this.remoteCommands.connect(opts);
@@ -8481,8 +8576,8 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
8481
8576
  await this.serviceCommands.stopService();
8482
8577
  }
8483
8578
  async agent(opts) {
8484
- const configPath = getConfigPath5();
8485
- const config2 = resolveConfigSecrets3(loadConfig12(), { configPath });
8579
+ const configPath = getConfigPath6();
8580
+ const config2 = resolveConfigSecrets3(loadConfig13(), { configPath });
8486
8581
  const workspace = getWorkspacePath10(config2.agents.defaults.workspace);
8487
8582
  const pluginRegistry = loadPluginRegistry(config2, workspace);
8488
8583
  const extensionRegistry = toExtensionRegistry(pluginRegistry);
@@ -8490,7 +8585,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
8490
8585
  const pluginChannelBindings = getPluginChannelBindings4(pluginRegistry);
8491
8586
  setPluginRuntimeBridge2({
8492
8587
  loadConfig: () => toPluginConfigView(
8493
- resolveConfigSecrets3(loadConfig12(), { configPath }),
8588
+ resolveConfigSecrets3(loadConfig13(), { configPath }),
8494
8589
  pluginChannelBindings
8495
8590
  ),
8496
8591
  writeConfigFile: async (nextConfigView) => {
@@ -8499,13 +8594,13 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
8499
8594
  "plugin runtime writeConfigFile expects an object config"
8500
8595
  );
8501
8596
  }
8502
- const current = loadConfig12();
8597
+ const current = loadConfig13();
8503
8598
  const next = mergePluginConfigView(
8504
8599
  current,
8505
8600
  nextConfigView,
8506
8601
  pluginChannelBindings
8507
8602
  );
8508
- saveConfig8(next);
8603
+ saveConfig9(next);
8509
8604
  }
8510
8605
  });
8511
8606
  try {
@@ -8531,7 +8626,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
8531
8626
  resolveMessageToolHints: ({ channel, accountId }) => resolvePluginChannelMessageToolHints2({
8532
8627
  registry: pluginRegistry,
8533
8628
  channel,
8534
- cfg: resolveConfigSecrets3(loadConfig12(), { configPath }),
8629
+ cfg: resolveConfigSecrets3(loadConfig13(), { configPath }),
8535
8630
  accountId
8536
8631
  })
8537
8632
  });
@@ -8554,7 +8649,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
8554
8649
  const historyDir = resolve12(historyFile, "..");
8555
8650
  mkdirSync8(historyDir, { recursive: true });
8556
8651
  const history = existsSync13(historyFile) ? readFileSync11(historyFile, "utf-8").split("\n").filter(Boolean) : [];
8557
- const rl = createInterface2({
8652
+ const rl = createInterface3({
8558
8653
  input: process.stdin,
8559
8654
  output: process.stdout
8560
8655
  });
@@ -8726,7 +8821,7 @@ ${this.logo} ${APP_NAME4} is ready! (${source})`);
8726
8821
  await this.diagnosticsCommands.doctor(opts);
8727
8822
  }
8728
8823
  async skillsInstall(options) {
8729
- const config2 = loadConfig12();
8824
+ const config2 = loadConfig13();
8730
8825
  const workdir = resolveSkillsInstallWorkdir({
8731
8826
  explicitWorkdir: options.workdir,
8732
8827
  configuredWorkspace: config2.agents.defaults.workspace
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nextclaw",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "description": "Lightweight personal AI assistant with CLI, multi-provider routing, and channel integrations.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -39,15 +39,15 @@
39
39
  "chokidar": "^3.6.0",
40
40
  "commander": "^12.1.0",
41
41
  "yaml": "^2.8.1",
42
- "@nextclaw/core": "0.9.2",
42
+ "@nextclaw/core": "0.9.3",
43
43
  "@nextclaw/ncp": "0.3.1",
44
- "@nextclaw/mcp": "0.1.1",
44
+ "@nextclaw/mcp": "0.1.2",
45
45
  "@nextclaw/ncp-agent-runtime": "0.2.1",
46
- "@nextclaw/runtime": "0.2.2",
47
- "@nextclaw/openclaw-compat": "0.3.5",
48
- "@nextclaw/ncp-mcp": "0.1.1",
46
+ "@nextclaw/ncp-mcp": "0.1.2",
47
+ "@nextclaw/runtime": "0.2.3",
49
48
  "@nextclaw/ncp-toolkit": "0.4.1",
50
- "@nextclaw/server": "0.10.0"
49
+ "@nextclaw/server": "0.10.2",
50
+ "@nextclaw/openclaw-compat": "0.3.6"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/node": "^20.17.6",