@nextclaw/server 0.15.6 → 0.15.7

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
@@ -2987,6 +2987,7 @@ const MARKETPLACE_ZH_COPY_BY_SLUG = {
2987
2987
  const MARKETPLACE_FETCH_TIMEOUT_MS = 12e3;
2988
2988
  const DOMESTIC_MARKETPLACE_FETCH_TIMEOUT_MS = 2e3;
2989
2989
  const DOMESTIC_MARKETPLACE_RETRY_ATTEMPTS = 2;
2990
+ const DOMESTIC_MARKETPLACE_MAX_SNAPSHOT_AGE_MS = 1200 * 1e3;
2990
2991
  function resolveMarketplaceBaseUrls(options) {
2991
2992
  const configured = options.marketplace?.apiBaseUrl?.trim();
2992
2993
  if (configured) return [configured.replace(/\/$/, "")];
@@ -3009,6 +3010,11 @@ function getMarketplaceFetchOptions(baseUrl) {
3009
3010
  function shouldFallbackMarketplaceResult(status) {
3010
3011
  return status === 408 || status === 429 || status >= 500;
3011
3012
  }
3013
+ function isStaleDomesticMarketplaceSnapshot(baseUrl, cachedAt, now = Date.now()) {
3014
+ if (baseUrl.replace(/\/$/, "") !== "https://api.nextclaw.net" || cachedAt === null) return false;
3015
+ const cachedAtMs = Date.parse(cachedAt);
3016
+ return !Number.isFinite(cachedAtMs) || now - cachedAtMs > DOMESTIC_MARKETPLACE_MAX_SNAPSHOT_AGE_MS;
3017
+ }
3012
3018
  //#endregion
3013
3019
  //#region src/features/marketplace/utils/marketplace-network-retry.utils.ts
3014
3020
  const MARKETPLACE_NETWORK_RETRY_ATTEMPTS = 5;
@@ -3086,6 +3092,11 @@ async function fetchMarketplaceDataFromBase(params) {
3086
3092
  message: error instanceof Error ? error.message : String(error)
3087
3093
  };
3088
3094
  }
3095
+ if (isStaleDomesticMarketplaceSnapshot(baseUrl, response.headers.get("x-nextclaw-mirror-cached-at"))) return {
3096
+ ok: false,
3097
+ status: 503,
3098
+ message: "domestic marketplace mirror snapshot is stale"
3099
+ };
3089
3100
  let payload = null;
3090
3101
  try {
3091
3102
  payload = await response.json();
@@ -3454,15 +3465,6 @@ function collectSkillMarketplaceInstalledView(options) {
3454
3465
  records: installed.records
3455
3466
  };
3456
3467
  }
3457
- function collectKnownSkillNames(options) {
3458
- const loader = createSkillsLoader(getWorkspacePathFromConfig(loadConfigOrDefault(options.configPath)));
3459
- return new Set((loader?.listSkills(false) ?? []).map((skill) => skill.name));
3460
- }
3461
- function isSupportedMarketplaceSkillItem(item, knownSkillNames) {
3462
- if (item.type !== "skill") return false;
3463
- if (item.install.kind === "marketplace") return true;
3464
- return item.install.kind === "builtin" && knownSkillNames.has(item.install.spec);
3465
- }
3466
3468
  function findUnsupportedSkillInstallKind(items) {
3467
3469
  for (const item of items) {
3468
3470
  if (item.type !== "skill") continue;
@@ -3545,12 +3547,11 @@ var SkillMarketplaceController = class {
3545
3547
  status: 502,
3546
3548
  message: `unsupported skill install kind from marketplace api: ${unsupportedKind}`
3547
3549
  };
3548
- const knownSkillNames = collectKnownSkillNames(this.options);
3549
3550
  return {
3550
3551
  ok: true,
3551
3552
  data: {
3552
3553
  ...data,
3553
- items: normalizedItems.filter((item) => isSupportedMarketplaceSkillItem(item, knownSkillNames))
3554
+ items: normalizedItems
3554
3555
  }
3555
3556
  };
3556
3557
  };
@@ -3594,11 +3595,9 @@ var SkillMarketplaceController = class {
3594
3595
  path: `/api/v1/skills/items/${slug}`
3595
3596
  });
3596
3597
  if (!result.ok) return c.json(err("MARKETPLACE_UNAVAILABLE", result.message), result.status);
3597
- const knownSkillNames = collectKnownSkillNames(this.options);
3598
3598
  const sanitized = normalizeMarketplaceItemForUi(sanitizeMarketplaceItemView(result.data));
3599
3599
  const unsupportedKind = findUnsupportedSkillInstallKind([sanitized]);
3600
3600
  if (unsupportedKind) return c.json(err("MARKETPLACE_CONTRACT_MISMATCH", `unsupported skill install kind from marketplace api: ${unsupportedKind}`), 502);
3601
- if (!isSupportedMarketplaceSkillItem(sanitized, knownSkillNames)) return c.json(err("NOT_FOUND", "marketplace item not supported by nextclaw"), 404);
3602
3601
  return c.json(ok(sanitized));
3603
3602
  };
3604
3603
  getItemContent = async (c) => {
@@ -3608,11 +3607,8 @@ var SkillMarketplaceController = class {
3608
3607
  path: `/api/v1/skills/items/${slug}`
3609
3608
  });
3610
3609
  if (!result.ok) return c.json(err("MARKETPLACE_UNAVAILABLE", result.message), result.status);
3611
- const knownSkillNames = collectKnownSkillNames(this.options);
3612
- const sanitized = normalizeMarketplaceItemForUi(sanitizeMarketplaceItemView(result.data));
3613
- const unsupportedKind = findUnsupportedSkillInstallKind([sanitized]);
3610
+ const unsupportedKind = findUnsupportedSkillInstallKind([normalizeMarketplaceItemForUi(sanitizeMarketplaceItemView(result.data))]);
3614
3611
  if (unsupportedKind) return c.json(err("MARKETPLACE_CONTRACT_MISMATCH", `unsupported skill install kind from marketplace api: ${unsupportedKind}`), 502);
3615
- if (!isSupportedMarketplaceSkillItem(sanitized, knownSkillNames)) return c.json(err("NOT_FOUND", "marketplace item not supported by nextclaw"), 404);
3616
3612
  const contentResult = await fetchMarketplaceData({
3617
3613
  baseUrls: this.marketplaceBaseUrls,
3618
3614
  path: `/api/v1/skills/items/${slug}/content`
@@ -3665,12 +3661,13 @@ var SkillMarketplaceController = class {
3665
3661
  }
3666
3662
  });
3667
3663
  if (!result.ok) return c.json(err("MARKETPLACE_UNAVAILABLE", result.message), result.status);
3668
- const knownSkillNames = collectKnownSkillNames(this.options);
3669
- const filteredItems = sanitizeMarketplaceListItems(result.data.items).map((item) => normalizeMarketplaceItemForUi(item)).filter((item) => isSupportedMarketplaceSkillItem(item, knownSkillNames));
3664
+ const items = sanitizeMarketplaceListItems(result.data.items).map((item) => normalizeMarketplaceItemForUi(item));
3665
+ const unsupportedKind = findUnsupportedSkillInstallKind(items);
3666
+ if (unsupportedKind) return c.json(err("MARKETPLACE_CONTRACT_MISMATCH", `unsupported skill install kind from marketplace api: ${unsupportedKind}`), 502);
3670
3667
  return c.json(ok({
3671
3668
  ...result.data,
3672
- total: filteredItems.length,
3673
- items: filteredItems
3669
+ total: items.length,
3670
+ items
3674
3671
  }));
3675
3672
  };
3676
3673
  };
@@ -6255,6 +6252,14 @@ async function startUiServer(gateway) {
6255
6252
  const resolvedAllowOrigin = allowOrigin ?? (isPanelAppRuntimeCors ? NULL_ORIGIN : null);
6256
6253
  if (resolvedAllowOrigin) for (const [name, value] of createCorsHeaders(resolvedAllowOrigin, allowHeaders, c.res.headers.get("Vary"))) c.res.headers.set(name, value);
6257
6254
  });
6255
+ const uiInjectionPath = join(dirname(gateway.configPath), "ui-inject.js");
6256
+ app.get("/api/ui-inject.js", async (c) => c.body(await readFile(uiInjectionPath, "utf-8").catch((error) => {
6257
+ if (error.code === "ENOENT") return "";
6258
+ throw error;
6259
+ }), 200, {
6260
+ "content-type": "application/javascript; charset=utf-8",
6261
+ "cache-control": "no-store"
6262
+ }));
6258
6263
  const eventStreamAuth = new EventStreamAuthService({
6259
6264
  uiAuth: authService,
6260
6265
  extensionAuth: gateway.extensions,