nextclaw 0.13.9 → 0.13.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli/index.js +178 -15
  2. package/package.json +5 -5
package/dist/cli/index.js CHANGED
@@ -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
- let parsed = null;
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
- nextclawProvider.apiBase = v1Base;
3029
- nextclawProvider.apiKey = token;
3030
- providers.nextclaw = nextclawProvider;
3031
- saveConfig6(config2, configPath);
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: Boolean(token),
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",
@@ -6424,6 +6558,9 @@ function decodeJwtPayload(token) {
6424
6558
  return null;
6425
6559
  }
6426
6560
  }
6561
+ function isPlatformSessionToken2(token) {
6562
+ return typeof token === "string" && token.startsWith("nca.");
6563
+ }
6427
6564
  function toRemoteRuntimeView(runtime2) {
6428
6565
  if (!runtime2) {
6429
6566
  return null;
@@ -6480,6 +6617,32 @@ var RemoteAccessHost = class {
6480
6617
  await this.deps.platformAuthCommands.loginResult(input);
6481
6618
  return this.getStatus();
6482
6619
  }
6620
+ async startBrowserAuth(input) {
6621
+ const result = await this.deps.platformAuthCommands.startBrowserAuth({
6622
+ apiBase: input.apiBase
6623
+ });
6624
+ return {
6625
+ sessionId: result.sessionId,
6626
+ verificationUri: result.verificationUri,
6627
+ expiresAt: result.expiresAt,
6628
+ intervalMs: result.intervalMs
6629
+ };
6630
+ }
6631
+ async pollBrowserAuth(input) {
6632
+ const config2 = loadConfig13(getConfigPath6());
6633
+ const result = await this.deps.platformAuthCommands.pollBrowserAuth({
6634
+ apiBase: normalizeOptionalString5(input.apiBase) ?? normalizeOptionalString5(config2.remote.platformApiBase) ?? normalizeOptionalString5(config2.providers.nextclaw?.apiBase) ?? void 0,
6635
+ sessionId: input.sessionId
6636
+ });
6637
+ if (result.status !== "authorized") {
6638
+ return result;
6639
+ }
6640
+ return {
6641
+ status: "authorized",
6642
+ email: result.email,
6643
+ role: result.role
6644
+ };
6645
+ }
6483
6646
  logout() {
6484
6647
  this.deps.platformAuthCommands.logout();
6485
6648
  return this.getStatus();
@@ -6592,7 +6755,7 @@ var RemoteAccessHost = class {
6592
6755
  };
6593
6756
  }
6594
6757
  readAccountView(params) {
6595
- if (!params.token) {
6758
+ if (!isPlatformSessionToken2(params.token)) {
6596
6759
  return {
6597
6760
  loggedIn: false,
6598
6761
  apiBase: params.apiBase,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nextclaw",
3
- "version": "0.13.9",
3
+ "version": "0.13.10",
4
4
  "description": "Lightweight personal AI assistant with CLI, multi-provider routing, and channel integrations.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -40,15 +40,15 @@
40
40
  "commander": "^12.1.0",
41
41
  "yaml": "^2.8.1",
42
42
  "@nextclaw/core": "0.9.5",
43
- "@nextclaw/mcp": "0.1.9",
43
+ "@nextclaw/mcp": "0.1.10",
44
44
  "@nextclaw/ncp": "0.3.1",
45
+ "@nextclaw/ncp-mcp": "0.1.10",
45
46
  "@nextclaw/ncp-agent-runtime": "0.2.1",
46
- "@nextclaw/ncp-mcp": "0.1.9",
47
47
  "@nextclaw/ncp-toolkit": "0.4.1",
48
+ "@nextclaw/remote": "0.1.6",
48
49
  "@nextclaw/runtime": "0.2.5",
49
- "@nextclaw/server": "0.10.9",
50
50
  "@nextclaw/openclaw-compat": "0.3.8",
51
- "@nextclaw/remote": "0.1.5"
51
+ "@nextclaw/server": "0.10.10"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/node": "^20.17.6",