@amaster.ai/runtime-cli 1.1.27 → 1.1.29

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.cjs CHANGED
@@ -33,18 +33,27 @@ var config_exports = {};
33
33
  __export(config_exports, {
34
34
  addApp: () => addApp,
35
35
  clearAuthSession: () => clearAuthSession,
36
+ ensureRegistry: () => ensureRegistry,
36
37
  getAccessToken: () => getAccessToken,
37
38
  getAppConfig: () => getAppConfig,
38
39
  getAuthSession: () => getAuthSession,
39
40
  getBaseURL: () => getBaseURL,
40
41
  getConfig: () => getConfig,
41
42
  getCurrentApp: () => getCurrentApp,
43
+ getCurrentRegistry: () => getCurrentRegistry,
44
+ getRegistryConfig: () => getRegistryConfig,
45
+ inferRegistryBaseURLFromAppBaseURL: () => inferRegistryBaseURLFromAppBaseURL,
42
46
  isAuthenticated: () => isAuthenticated,
43
47
  listApps: () => listApps,
48
+ listRegistries: () => listRegistries,
49
+ normalizeRegistryBaseURL: () => normalizeRegistryBaseURL,
44
50
  removeApp: () => removeApp,
51
+ resolveAppBaseURL: () => resolveAppBaseURL,
52
+ resolveRegistry: () => resolveRegistry,
45
53
  saveAuthSession: () => saveAuthSession,
46
54
  saveConfig: () => saveConfig,
47
55
  setCurrentApp: () => setCurrentApp,
56
+ setCurrentRegistry: () => setCurrentRegistry,
48
57
  shouldRefreshToken: () => shouldRefreshToken
49
58
  });
50
59
  function getConfig() {
@@ -107,6 +116,137 @@ function listApps() {
107
116
  const config = getConfig();
108
117
  return Object.keys(config.apps);
109
118
  }
119
+ function listRegistries() {
120
+ const config = getConfig();
121
+ const currentRegistry = config.currentRegistry || DEFAULT_REGISTRY_NAME;
122
+ const registryMap = /* @__PURE__ */ new Map();
123
+ for (const [name, baseURL] of Object.entries(BUILTIN_REGISTRY_DEFINITIONS)) {
124
+ registryMap.set(name, {
125
+ name,
126
+ baseURL,
127
+ builtin: true
128
+ });
129
+ }
130
+ for (const [name, registry] of Object.entries(config.registries || {})) {
131
+ registryMap.set(name, {
132
+ name,
133
+ baseURL: registry.baseURL,
134
+ builtin: false
135
+ });
136
+ }
137
+ const registries = Array.from(registryMap.values()).sort((left, right) => left.name.localeCompare(right.name));
138
+ const currentResolved = resolveRegistry(currentRegistry);
139
+ return registries.map((registry) => ({
140
+ ...registry,
141
+ name: registry.name === currentResolved.name ? registry.name : registry.name
142
+ }));
143
+ }
144
+ function getCurrentRegistry() {
145
+ const config = getConfig();
146
+ return config.currentRegistry || DEFAULT_REGISTRY_NAME;
147
+ }
148
+ function setCurrentRegistry(registryRef) {
149
+ const resolved = ensureRegistry(registryRef);
150
+ const config = getConfig();
151
+ config.currentRegistry = resolved.name;
152
+ saveConfig(config);
153
+ return resolved;
154
+ }
155
+ function getRegistryConfig(name) {
156
+ const config = getConfig();
157
+ return config.registries?.[name] || null;
158
+ }
159
+ function ensureRegistry(registryRef) {
160
+ const normalizedRef = registryRef.trim();
161
+ if (!normalizedRef) {
162
+ throw new Error("Registry cannot be empty");
163
+ }
164
+ const builtinBaseURL = BUILTIN_REGISTRY_DEFINITIONS[normalizedRef];
165
+ if (builtinBaseURL) {
166
+ return {
167
+ name: normalizedRef,
168
+ baseURL: builtinBaseURL,
169
+ builtin: true
170
+ };
171
+ }
172
+ const config = getConfig();
173
+ const existing = config.registries?.[normalizedRef];
174
+ if (existing) {
175
+ return {
176
+ name: normalizedRef,
177
+ baseURL: existing.baseURL,
178
+ builtin: false
179
+ };
180
+ }
181
+ const normalizedBaseURL = normalizeRegistryBaseURL(normalizedRef);
182
+ for (const [name, baseURL] of Object.entries(BUILTIN_REGISTRY_DEFINITIONS)) {
183
+ if (normalizeRegistryBaseURL(baseURL) === normalizedBaseURL) {
184
+ return {
185
+ name,
186
+ baseURL,
187
+ builtin: true
188
+ };
189
+ }
190
+ }
191
+ const inferredName = inferRegistryName(normalizedBaseURL);
192
+ const current = config.registries?.[inferredName];
193
+ const nextRegistry = {
194
+ baseURL: normalizedBaseURL,
195
+ createdAt: current?.createdAt || (/* @__PURE__ */ new Date()).toISOString()
196
+ };
197
+ config.registries = {
198
+ ...config.registries || {},
199
+ [inferredName]: nextRegistry
200
+ };
201
+ saveConfig(config);
202
+ return {
203
+ name: inferredName,
204
+ baseURL: normalizedBaseURL,
205
+ builtin: false
206
+ };
207
+ }
208
+ function resolveRegistry(registryRef) {
209
+ return ensureRegistry(registryRef || getCurrentRegistry());
210
+ }
211
+ function normalizeRegistryBaseURL(value) {
212
+ const trimmed = value.trim();
213
+ if (!trimmed) {
214
+ throw new Error("Registry cannot be empty");
215
+ }
216
+ const withProtocol = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
217
+ const parsed = new URL(withProtocol);
218
+ if (parsed.username || parsed.password || parsed.search || parsed.hash) {
219
+ throw new Error(`Unsupported registry URL: ${value}`);
220
+ }
221
+ if (parsed.pathname && parsed.pathname !== "/") {
222
+ throw new Error(`Registry URL must not include a path: ${value}`);
223
+ }
224
+ parsed.pathname = "";
225
+ return parsed.toString().replace(/\/$/, "");
226
+ }
227
+ function resolveAppBaseURL(appCode, registryRef) {
228
+ const resolved = resolveRegistry(registryRef);
229
+ const registryUrl = new URL(resolved.baseURL);
230
+ if (isLocalLikeHost(registryUrl.hostname)) {
231
+ throw new Error(`Cannot infer app URL from registry ${resolved.baseURL}; please pass --url explicitly`);
232
+ }
233
+ return `${registryUrl.protocol}//${appCode}.${registryUrl.host}`;
234
+ }
235
+ function inferRegistryBaseURLFromAppBaseURL(appBaseURL, appCode) {
236
+ const parsed = new URL(appBaseURL);
237
+ const hostnameParts = parsed.hostname.split(".");
238
+ if (hostnameParts.length <= 2 || isLocalLikeHost(parsed.hostname)) {
239
+ parsed.pathname = "";
240
+ return parsed.toString().replace(/\/$/, "");
241
+ }
242
+ if (appCode && parsed.hostname.startsWith(`${appCode}.`)) {
243
+ parsed.hostname = parsed.hostname.slice(appCode.length + 1);
244
+ } else {
245
+ parsed.hostname = hostnameParts.slice(1).join(".");
246
+ }
247
+ parsed.pathname = "";
248
+ return parsed.toString().replace(/\/$/, "");
249
+ }
110
250
  function getBaseURL(appCode) {
111
251
  const code = appCode || getCurrentApp();
112
252
  if (!code) return null;
@@ -161,11 +301,29 @@ function shouldRefreshToken(appCode) {
161
301
  const fiveMinutes = 5 * 60 * 1e3;
162
302
  return expiresAt.getTime() - now.getTime() < fiveMinutes;
163
303
  }
164
- var AMASTER_CONFIG_DIR, CONFIG_FILE;
304
+ function inferRegistryName(baseURL) {
305
+ const parsed = new URL(baseURL);
306
+ return parsed.hostname.replace(/\./g, "-");
307
+ }
308
+ function isLocalLikeHost(hostname) {
309
+ if (hostname === "localhost") {
310
+ return true;
311
+ }
312
+ if (/^\d{1,3}(\.\d{1,3}){3}$/.test(hostname)) {
313
+ return true;
314
+ }
315
+ return false;
316
+ }
317
+ var AMASTER_CONFIG_DIR, CONFIG_FILE, DEFAULT_REGISTRY_NAME, BUILTIN_REGISTRY_DEFINITIONS;
165
318
  var init_config = __esm({
166
319
  "src/config.ts"() {
167
320
  AMASTER_CONFIG_DIR = path.join(os.homedir(), ".amaster");
168
321
  CONFIG_FILE = path.join(AMASTER_CONFIG_DIR, "config.json");
322
+ DEFAULT_REGISTRY_NAME = "helige";
323
+ BUILTIN_REGISTRY_DEFINITIONS = {
324
+ helige: "https://helige.cn",
325
+ "helige-int": "https://helige-int.cn"
326
+ };
169
327
  }
170
328
  });
171
329
 
@@ -2801,6 +2959,8 @@ async function initOpenClaw(options) {
2801
2959
  }
2802
2960
  addApp(options.appCode, {
2803
2961
  baseURL: options.baseURL,
2962
+ registry: options.registry,
2963
+ registryBaseURL: options.registryBaseURL,
2804
2964
  ossEndpoint,
2805
2965
  initializedAt: (/* @__PURE__ */ new Date()).toISOString()
2806
2966
  });
@@ -2814,6 +2974,8 @@ async function initOpenClaw(options) {
2814
2974
  {
2815
2975
  appCode: options.appCode,
2816
2976
  baseURL: options.baseURL,
2977
+ registry: options.registry || null,
2978
+ registryBaseURL: options.registryBaseURL || null,
2817
2979
  ossEndpoint,
2818
2980
  openClawDetected: false,
2819
2981
  installedSkills: 0,
@@ -2829,6 +2991,9 @@ async function initOpenClaw(options) {
2829
2991
  console.log(chalk4__default.default.blue("\n\u{1F4CB} Configuration:\n"));
2830
2992
  console.log(` App Code: ${chalk4__default.default.green(options.appCode)}`);
2831
2993
  console.log(` Base URL: ${chalk4__default.default.gray(options.baseURL)}`);
2994
+ if (options.registryBaseURL) {
2995
+ console.log(` Registry: ${chalk4__default.default.gray(`${options.registry || "custom"} -> ${options.registryBaseURL}`)}`);
2996
+ }
2832
2997
  console.log();
2833
2998
  }
2834
2999
  spinner.start("Downloading skills...");
@@ -2882,12 +3047,16 @@ async function initOpenClaw(options) {
2882
3047
  const config = getAppConfig(app);
2883
3048
  return {
2884
3049
  appCode: app,
2885
- baseURL: config?.baseURL || null
3050
+ baseURL: config?.baseURL || null,
3051
+ registry: config?.registry || null,
3052
+ registryBaseURL: config?.registryBaseURL || null
2886
3053
  };
2887
3054
  });
2888
3055
  const summary = {
2889
3056
  appCode: options.appCode,
2890
3057
  baseURL: options.baseURL,
3058
+ registry: options.registry || null,
3059
+ registryBaseURL: options.registryBaseURL || null,
2891
3060
  ossEndpoint,
2892
3061
  openClawDetected: true,
2893
3062
  installedSkills,
@@ -3068,6 +3237,24 @@ function createAmasterClient(appCode) {
3068
3237
  }
3069
3238
  return client$1;
3070
3239
  }
3240
+ function resolveInitBaseURL(options) {
3241
+ if (options.url) {
3242
+ const resolvedRegistry2 = resolveRegistry(
3243
+ options.registry || inferRegistryBaseURLFromAppBaseURL(options.url, options.appCode)
3244
+ );
3245
+ return {
3246
+ baseURL: options.url,
3247
+ registryName: resolvedRegistry2.name,
3248
+ registryBaseURL: resolvedRegistry2.baseURL
3249
+ };
3250
+ }
3251
+ const resolvedRegistry = resolveRegistry(options.registry);
3252
+ return {
3253
+ baseURL: resolveAppBaseURL(options.appCode, resolvedRegistry.name),
3254
+ registryName: resolvedRegistry.name,
3255
+ registryBaseURL: resolvedRegistry.baseURL
3256
+ };
3257
+ }
3071
3258
  var program = new commander.Command();
3072
3259
  program.name("amaster").description("CLI for Amaster SDK - Multi-app support for OpenClaw").version(resolveCliVersion());
3073
3260
  program.command("apps").description("List all configured apps").addOption(createFormatOption()).action((options) => {
@@ -3078,6 +3265,8 @@ program.command("apps").description("List all configured apps").addOption(create
3078
3265
  return {
3079
3266
  appCode,
3080
3267
  baseURL: config?.baseURL || null,
3268
+ registry: config?.registry || null,
3269
+ registryBaseURL: config?.registryBaseURL || null,
3081
3270
  authenticated: isAuthenticated(appCode),
3082
3271
  current: appCode === current
3083
3272
  };
@@ -3094,6 +3283,9 @@ program.command("apps").description("List all configured apps").addOption(create
3094
3283
  const prefix = app.current ? chalk4__default.default.green("\u2192 ") : " ";
3095
3284
  console.log(`${prefix}${chalk4__default.default.bold(app.appCode)}${app.current ? chalk4__default.default.green(" (current)") : ""}`);
3096
3285
  console.log(` ${chalk4__default.default.gray(app.baseURL || "No URL")}`);
3286
+ if (app.registryBaseURL) {
3287
+ console.log(` ${chalk4__default.default.gray(`registry: ${app.registry} -> ${app.registryBaseURL}`)}`);
3288
+ }
3097
3289
  console.log(
3098
3290
  ` ${app.authenticated ? chalk4__default.default.green("\u25CF Authenticated") : chalk4__default.default.yellow("\u25CB Not authenticated")}`
3099
3291
  );
@@ -3104,6 +3296,45 @@ program.command("apps").description("List all configured apps").addOption(create
3104
3296
  }
3105
3297
  });
3106
3298
  });
3299
+ var registryCmd = program.command("registry").description("Manage addon and app registries");
3300
+ registryCmd.command("list").alias("ls").description("List available registries").addOption(createFormatOption()).action((options) => {
3301
+ const currentRegistry = getCurrentRegistry();
3302
+ const registries = listRegistries().map((registry) => ({
3303
+ ...registry,
3304
+ current: registry.name === currentRegistry
3305
+ }));
3306
+ renderOutput(registries, {
3307
+ format: options.format,
3308
+ pretty: () => {
3309
+ console.log(chalk4__default.default.blue("\n\u{1F310} Registries\n"));
3310
+ for (const registry of registries) {
3311
+ const prefix = registry.current ? chalk4__default.default.green("\u2192 ") : " ";
3312
+ const builtin = registry.builtin ? chalk4__default.default.gray("builtin") : chalk4__default.default.gray("custom");
3313
+ console.log(`${prefix}${chalk4__default.default.bold(registry.name)}${registry.current ? chalk4__default.default.green(" (current)") : ""}`);
3314
+ console.log(` ${chalk4__default.default.gray(registry.baseURL)} ${builtin}`);
3315
+ }
3316
+ console.log();
3317
+ }
3318
+ });
3319
+ });
3320
+ registryCmd.command("use <registry>").description("Set the default registry by name or URL").addOption(createFormatOption()).action((registry, options) => {
3321
+ const resolved = setCurrentRegistry(registry);
3322
+ renderOutput(
3323
+ {
3324
+ name: resolved.name,
3325
+ baseURL: resolved.baseURL,
3326
+ builtin: resolved.builtin,
3327
+ current: true
3328
+ },
3329
+ {
3330
+ format: options.format,
3331
+ pretty: () => {
3332
+ console.log(chalk4__default.default.green(`\u2705 Now using registry: ${resolved.name}`));
3333
+ console.log(chalk4__default.default.gray(resolved.baseURL));
3334
+ }
3335
+ }
3336
+ );
3337
+ });
3107
3338
  program.command("use <app-code>").description("Set the default app for subsequent commands").addOption(createFormatOption()).action((appCode, options) => {
3108
3339
  if (setCurrentApp(appCode)) {
3109
3340
  renderOutput(
@@ -3123,10 +3354,17 @@ program.command("use <app-code>").description("Set the default app for subsequen
3123
3354
  process.exit(1);
3124
3355
  }
3125
3356
  });
3126
- program.command("init").description("Initialize an app for OpenClaw integration").requiredOption("--app-code <code>", "Application code (e.g., fhv94bto1)").requiredOption("--url <url>", "Base URL (e.g., https://fhv94bto1.helige.cn)").option("--api-key <key>", "API Key for OSS access").option("--oss-endpoint <endpoint>", "OSS endpoint").option("--force", "Reinitialize an existing app").addOption(createFormatOption()).action(async (options) => {
3357
+ program.command("init").description("Initialize an app for OpenClaw integration").requiredOption("--app-code <code>", "Application code (e.g., fhv94bto1)").option("--url <url>", "Base URL (e.g., https://fhv94bto1.helige.cn)").option("--registry <registry>", "Registry name or URL (default: current registry)").option("--api-key <key>", "API Key for OSS access").option("--oss-endpoint <endpoint>", "OSS endpoint").option("--force", "Reinitialize an existing app").addOption(createFormatOption()).action(async (options) => {
3358
+ const resolvedInit = resolveInitBaseURL({
3359
+ appCode: options.appCode,
3360
+ url: options.url,
3361
+ registry: options.registry
3362
+ });
3127
3363
  await initOpenClaw({
3128
3364
  appCode: options.appCode,
3129
- baseURL: options.url,
3365
+ baseURL: resolvedInit.baseURL,
3366
+ registry: resolvedInit.registryName,
3367
+ registryBaseURL: resolvedInit.registryBaseURL,
3130
3368
  apiKey: options.apiKey,
3131
3369
  ossEndpoint: options.ossEndpoint,
3132
3370
  force: options.force,
@@ -3683,19 +3921,29 @@ if (isDirectCliExecution()) {
3683
3921
  exports.addApp = addApp;
3684
3922
  exports.clearAuthSession = clearAuthSession;
3685
3923
  exports.createAmasterClient = createAmasterClient;
3924
+ exports.ensureRegistry = ensureRegistry;
3686
3925
  exports.getAccessToken = getAccessToken;
3687
3926
  exports.getAppConfig = getAppConfig;
3688
3927
  exports.getAuthSession = getAuthSession;
3689
3928
  exports.getBaseURL = getBaseURL;
3690
3929
  exports.getConfig = getConfig;
3691
3930
  exports.getCurrentApp = getCurrentApp;
3931
+ exports.getCurrentRegistry = getCurrentRegistry;
3932
+ exports.getRegistryConfig = getRegistryConfig;
3933
+ exports.inferRegistryBaseURLFromAppBaseURL = inferRegistryBaseURLFromAppBaseURL;
3692
3934
  exports.isAuthenticated = isAuthenticated;
3693
3935
  exports.listApps = listApps;
3936
+ exports.listRegistries = listRegistries;
3937
+ exports.normalizeRegistryBaseURL = normalizeRegistryBaseURL;
3694
3938
  exports.removeApp = removeApp;
3939
+ exports.resolveAppBaseURL = resolveAppBaseURL;
3695
3940
  exports.resolveAppCode = resolveAppCode;
3941
+ exports.resolveInitBaseURL = resolveInitBaseURL;
3942
+ exports.resolveRegistry = resolveRegistry;
3696
3943
  exports.saveAuthSession = saveAuthSession;
3697
3944
  exports.saveConfig = saveConfig;
3698
3945
  exports.setCurrentApp = setCurrentApp;
3946
+ exports.setCurrentRegistry = setCurrentRegistry;
3699
3947
  exports.shouldRefreshToken = shouldRefreshToken;
3700
3948
  //# sourceMappingURL=index.cjs.map
3701
3949
  //# sourceMappingURL=index.cjs.map