@lobehub/cli 0.0.23 → 0.0.24

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/index.js CHANGED
@@ -17187,6 +17187,118 @@ var GatewayClient = class extends EventEmitter {
17187
17187
  }
17188
17188
  };
17189
17189
 
17190
+ //#endregion
17191
+ //#region src/auth/apiKey.ts
17192
+ async function getUserIdFromApiKey(apiKey, serverUrl) {
17193
+ const normalizedServerUrl = normalizeUrl(serverUrl) || resolveServerUrl();
17194
+ const response = await fetch(`${normalizedServerUrl}/api/v1/users/me?includeCount=0`, { headers: { Authorization: `Bearer ${apiKey}` } });
17195
+ let body;
17196
+ try {
17197
+ body = await response.json();
17198
+ } catch {
17199
+ throw new Error(`Failed to parse response from ${normalizedServerUrl}/api/v1/users/me?includeCount=0.`);
17200
+ }
17201
+ if (!response.ok || body?.success === false) throw new Error(body?.error || body?.message || `Request failed with status ${response.status}.`);
17202
+ const userId = body?.data?.id || body?.data?.userId;
17203
+ if (!userId) throw new Error("Current user response did not include a user id.");
17204
+ return userId;
17205
+ }
17206
+
17207
+ //#endregion
17208
+ //#region src/auth/resolveToken.ts
17209
+ /**
17210
+ * Parse the `sub` claim from a JWT without verifying the signature.
17211
+ */
17212
+ function parseJwtSub(token) {
17213
+ try {
17214
+ return JSON.parse(Buffer.from(token.split(".")[1], "base64url").toString()).sub;
17215
+ } catch {
17216
+ return;
17217
+ }
17218
+ }
17219
+ /**
17220
+ * Resolve an access token from explicit options, environment variables, or stored credentials.
17221
+ * Exits the process if no token can be resolved.
17222
+ */
17223
+ async function resolveToken(options) {
17224
+ const envJwt = process.env.LOBEHUB_JWT;
17225
+ if (envJwt) {
17226
+ const serverUrl = resolveServerUrl();
17227
+ const userId = parseJwtSub(envJwt);
17228
+ if (!userId) {
17229
+ log$7.error("Could not extract userId from LOBEHUB_JWT.");
17230
+ process.exit(1);
17231
+ }
17232
+ log$7.debug("Using LOBEHUB_JWT from environment");
17233
+ return {
17234
+ serverUrl,
17235
+ token: envJwt,
17236
+ tokenType: "jwt",
17237
+ userId
17238
+ };
17239
+ }
17240
+ if (options.token) {
17241
+ const userId = parseJwtSub(options.token);
17242
+ if (!userId) {
17243
+ log$7.error("Could not extract userId from token. Provide --user-id explicitly.");
17244
+ process.exit(1);
17245
+ }
17246
+ return {
17247
+ serverUrl: resolveServerUrl(),
17248
+ token: options.token,
17249
+ tokenType: "jwt",
17250
+ userId
17251
+ };
17252
+ }
17253
+ if (options.serviceToken) {
17254
+ if (!options.userId) {
17255
+ log$7.error("--user-id is required when using --service-token");
17256
+ process.exit(1);
17257
+ }
17258
+ return {
17259
+ serverUrl: resolveServerUrl(),
17260
+ token: options.serviceToken,
17261
+ tokenType: "serviceToken",
17262
+ userId: options.userId
17263
+ };
17264
+ }
17265
+ const envApiKey = process.env[CLI_API_KEY_ENV];
17266
+ if (envApiKey) try {
17267
+ const serverUrl = resolveServerUrl();
17268
+ const userId = await getUserIdFromApiKey(envApiKey, serverUrl);
17269
+ log$7.debug(`Using ${CLI_API_KEY_ENV} from environment`);
17270
+ return {
17271
+ serverUrl,
17272
+ token: envApiKey,
17273
+ tokenType: "apiKey",
17274
+ userId
17275
+ };
17276
+ } catch (error) {
17277
+ const message = error instanceof Error ? error.message : String(error);
17278
+ log$7.error(`Failed to validate ${CLI_API_KEY_ENV}: ${message}`);
17279
+ process.exit(1);
17280
+ }
17281
+ const result = await getValidToken();
17282
+ if (result) {
17283
+ log$7.debug("Using stored credentials");
17284
+ const { credentials } = result;
17285
+ const serverUrl = resolveServerUrl();
17286
+ const userId = parseJwtSub(credentials.accessToken);
17287
+ if (!userId) {
17288
+ log$7.error("Stored token is invalid. Run 'lh login' again.");
17289
+ process.exit(1);
17290
+ }
17291
+ return {
17292
+ serverUrl,
17293
+ token: credentials.accessToken,
17294
+ tokenType: "jwt",
17295
+ userId
17296
+ };
17297
+ }
17298
+ log$7.error(`No authentication found. Run 'lh login' first, or set ${CLI_API_KEY_ENV}, or provide --token.`);
17299
+ process.exit(1);
17300
+ }
17301
+
17190
17302
  //#endregion
17191
17303
  //#region node_modules/.pnpm/node-machine-id@1.1.12/node_modules/node-machine-id/dist/index.js
17192
17304
  var require_dist$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
@@ -18066,115 +18178,33 @@ const deriveDeviceId = (userId, options = {}) => {
18066
18178
  };
18067
18179
 
18068
18180
  //#endregion
18069
- //#region src/auth/apiKey.ts
18070
- async function getUserIdFromApiKey(apiKey, serverUrl) {
18071
- const normalizedServerUrl = normalizeUrl(serverUrl) || resolveServerUrl();
18072
- const response = await fetch(`${normalizedServerUrl}/api/v1/users/me`, { headers: { Authorization: `Bearer ${apiKey}` } });
18073
- let body;
18074
- try {
18075
- body = await response.json();
18076
- } catch {
18077
- throw new Error(`Failed to parse response from ${normalizedServerUrl}/api/v1/users/me.`);
18078
- }
18079
- if (!response.ok || body?.success === false) throw new Error(body?.error || body?.message || `Request failed with status ${response.status}.`);
18080
- const userId = body?.data?.id || body?.data?.userId;
18081
- if (!userId) throw new Error("Current user response did not include a user id.");
18082
- return userId;
18083
- }
18084
-
18085
- //#endregion
18086
- //#region src/auth/resolveToken.ts
18181
+ //#region src/device/register.ts
18087
18182
  /**
18088
- * Parse the `sub` claim from a JWT without verifying the signature.
18183
+ * Resolve a stable device identity. An explicit `--device-id` wins (lets a user
18184
+ * pin a VM to a fixed identity); otherwise derive from the machine id so the
18185
+ * same machine + user maps to one device across reconnects. Returns undefined
18186
+ * when neither an explicit id nor a userId is available.
18089
18187
  */
18090
- function parseJwtSub(token) {
18091
- try {
18092
- return JSON.parse(Buffer.from(token.split(".")[1], "base64url").toString()).sub;
18093
- } catch {
18094
- return;
18095
- }
18188
+ function resolveDeviceIdentity(userId, explicitDeviceId) {
18189
+ if (explicitDeviceId) return {
18190
+ deviceId: explicitDeviceId,
18191
+ identitySource: "fallback"
18192
+ };
18193
+ if (userId) return deriveDeviceId(userId);
18096
18194
  }
18097
18195
  /**
18098
- * Resolve an access token from explicit options, environment variables, or stored credentials.
18099
- * Exits the process if no token can be resolved.
18196
+ * Register this device in the server registry. Shared by `lh login` (so the
18197
+ * device row exists right after auth) and `lh connect` (so the row exists
18198
+ * before the WS opens). Best-effort by contract: callers should wrap this in a
18199
+ * try/catch and treat any failure as non-fatal.
18100
18200
  */
18101
- async function resolveToken(options) {
18102
- const envJwt = process.env.LOBEHUB_JWT;
18103
- if (envJwt) {
18104
- const serverUrl = resolveServerUrl();
18105
- const userId = parseJwtSub(envJwt);
18106
- if (!userId) {
18107
- log$7.error("Could not extract userId from LOBEHUB_JWT.");
18108
- process.exit(1);
18109
- }
18110
- log$7.debug("Using LOBEHUB_JWT from environment");
18111
- return {
18112
- serverUrl,
18113
- token: envJwt,
18114
- tokenType: "jwt",
18115
- userId
18116
- };
18117
- }
18118
- if (options.token) {
18119
- const userId = parseJwtSub(options.token);
18120
- if (!userId) {
18121
- log$7.error("Could not extract userId from token. Provide --user-id explicitly.");
18122
- process.exit(1);
18123
- }
18124
- return {
18125
- serverUrl: resolveServerUrl(),
18126
- token: options.token,
18127
- tokenType: "jwt",
18128
- userId
18129
- };
18130
- }
18131
- if (options.serviceToken) {
18132
- if (!options.userId) {
18133
- log$7.error("--user-id is required when using --service-token");
18134
- process.exit(1);
18135
- }
18136
- return {
18137
- serverUrl: resolveServerUrl(),
18138
- token: options.serviceToken,
18139
- tokenType: "serviceToken",
18140
- userId: options.userId
18141
- };
18142
- }
18143
- const envApiKey = process.env[CLI_API_KEY_ENV];
18144
- if (envApiKey) try {
18145
- const serverUrl = resolveServerUrl();
18146
- const userId = await getUserIdFromApiKey(envApiKey, serverUrl);
18147
- log$7.debug(`Using ${CLI_API_KEY_ENV} from environment`);
18148
- return {
18149
- serverUrl,
18150
- token: envApiKey,
18151
- tokenType: "apiKey",
18152
- userId
18153
- };
18154
- } catch (error) {
18155
- const message = error instanceof Error ? error.message : String(error);
18156
- log$7.error(`Failed to validate ${CLI_API_KEY_ENV}: ${message}`);
18157
- process.exit(1);
18158
- }
18159
- const result = await getValidToken();
18160
- if (result) {
18161
- log$7.debug("Using stored credentials");
18162
- const { credentials } = result;
18163
- const serverUrl = resolveServerUrl();
18164
- const userId = parseJwtSub(credentials.accessToken);
18165
- if (!userId) {
18166
- log$7.error("Stored token is invalid. Run 'lh login' again.");
18167
- process.exit(1);
18168
- }
18169
- return {
18170
- serverUrl,
18171
- token: credentials.accessToken,
18172
- tokenType: "jwt",
18173
- userId
18174
- };
18175
- }
18176
- log$7.error(`No authentication found. Run 'lh login' first, or set ${CLI_API_KEY_ENV}, or provide --token.`);
18177
- process.exit(1);
18201
+ async function registerDevice(auth, identity) {
18202
+ await createLambdaClient(auth).device.register.mutate({
18203
+ deviceId: identity.deviceId,
18204
+ hostname: os.hostname(),
18205
+ identitySource: identity.identitySource,
18206
+ platform: process.platform
18207
+ });
18178
18208
  }
18179
18209
 
18180
18210
  //#endregion
@@ -206936,10 +206966,7 @@ async function runConnect(options, isDaemonChild) {
206936
206966
  gatewayUrl
206937
206967
  });
206938
206968
  const resolvedGatewayUrl = gatewayUrl || "https://device-gateway.lobehub.com";
206939
- const identity = options.deviceId ? {
206940
- deviceId: options.deviceId,
206941
- identitySource: "fallback"
206942
- } : auth.userId ? deriveDeviceId(auth.userId) : void 0;
206969
+ const identity = resolveDeviceIdentity(auth.userId, options.deviceId);
206943
206970
  const client = new GatewayClient({
206944
206971
  channel: process.env.LOBEHUB_CLI_CHANNEL || "cli",
206945
206972
  connectionId: loadOrCreateConnectionId(),
@@ -207081,12 +207108,7 @@ async function runConnect(options, isDaemonChild) {
207081
207108
  process.exit(0);
207082
207109
  });
207083
207110
  if (identity) try {
207084
- await createLambdaClient(auth).device.register.mutate({
207085
- deviceId: identity.deviceId,
207086
- hostname: os.hostname(),
207087
- identitySource: identity.identitySource,
207088
- platform: process.platform
207089
- });
207111
+ await registerDevice(auth, identity);
207090
207112
  } catch (err) {
207091
207113
  error(`Device registration failed (non-fatal): ${err.message}`);
207092
207114
  }
@@ -211162,6 +211184,16 @@ function registerLoginCommand(program) {
211162
211184
  gatewayUrl: existingSettings.gatewayUrl,
211163
211185
  serverUrl
211164
211186
  } : { serverUrl });
211187
+ const identity = resolveDeviceIdentity(parseJwtSub(body.access_token));
211188
+ if (identity && identity.identitySource !== "fallback") try {
211189
+ await registerDevice({
211190
+ serverUrl,
211191
+ token: body.access_token,
211192
+ tokenType: "jwt"
211193
+ }, identity);
211194
+ } catch (err) {
211195
+ log$7.warn(`Device registration failed (non-fatal): ${err.message}`);
211196
+ }
211165
211197
  log$7.info("Login successful! Credentials saved.");
211166
211198
  return;
211167
211199
  }
package/man/man1/lh.1 CHANGED
@@ -1,6 +1,6 @@
1
1
  .\" Code generated by `npm run man:generate`; DO NOT EDIT.
2
2
  .\" Manual command details come from the Commander command tree.
3
- .TH LH 1 "" "@lobehub/cli 0.0.23" "User Commands"
3
+ .TH LH 1 "" "@lobehub/cli 0.0.24" "User Commands"
4
4
  .SH NAME
5
5
  lh \- LobeHub CLI \- manage and connect to LobeHub services
6
6
  .SH SYNOPSIS
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/cli",
3
- "version": "0.0.23",
3
+ "version": "0.0.24",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "lh": "./dist/index.js",
@@ -31,11 +31,11 @@
31
31
  "tsdown": "^0.21.4",
32
32
  "typescript": "^6.0.3",
33
33
  "ws": "^8.18.1",
34
+ "@lobechat/device-gateway-client": "1.0.0",
34
35
  "@lobechat/agent-gateway-client": "1.0.0",
35
- "@lobechat/device-identity": "1.0.0",
36
36
  "@lobechat/local-file-shell": "1.0.0",
37
- "@lobechat/heterogeneous-agents": "1.0.0",
38
- "@lobechat/device-gateway-client": "1.0.0"
37
+ "@lobechat/device-identity": "1.0.0",
38
+ "@lobechat/heterogeneous-agents": "1.0.0"
39
39
  },
40
40
  "publishConfig": {
41
41
  "access": "public",