@nextclaw/service 0.2.17 → 0.2.18

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 (23) hide show
  1. package/dist/services/cron/cron-local.service.d.ts +2 -1
  2. package/dist/services/cron/cron-local.service.d.ts.map +1 -1
  3. package/dist/services/marketplace/skills-query.service.d.ts +4 -2
  4. package/dist/services/marketplace/skills-query.service.d.ts.map +1 -1
  5. package/dist/services/marketplace/skills-query.service.js +45 -26
  6. package/dist/services/marketplace/skills-query.service.js.map +1 -1
  7. package/dist/services/runtime/runtime-config-init.service.d.ts +1 -1
  8. package/dist/utils/marketplace/marketplace-client.utils.d.ts +6 -1
  9. package/dist/utils/marketplace/marketplace-client.utils.d.ts.map +1 -1
  10. package/dist/utils/marketplace/marketplace-client.utils.js +36 -21
  11. package/dist/utils/marketplace/marketplace-client.utils.js.map +1 -1
  12. package/dist/utils/marketplace/marketplace-network-retry.utils.d.ts +5 -1
  13. package/dist/utils/marketplace/marketplace-network-retry.utils.d.ts.map +1 -1
  14. package/dist/utils/marketplace/marketplace-network-retry.utils.js +6 -4
  15. package/dist/utils/marketplace/marketplace-network-retry.utils.js.map +1 -1
  16. package/dist/utils/marketplace/marketplace-read-source.utils.d.ts +21 -0
  17. package/dist/utils/marketplace/marketplace-read-source.utils.d.ts.map +1 -0
  18. package/dist/utils/marketplace/marketplace-read-source.utils.js +51 -0
  19. package/dist/utils/marketplace/marketplace-read-source.utils.js.map +1 -0
  20. package/dist/utils/marketplace/marketplace-skill-lifecycle.utils.d.ts.map +1 -1
  21. package/dist/utils/marketplace/marketplace-skill-lifecycle.utils.js +14 -11
  22. package/dist/utils/marketplace/marketplace-skill-lifecycle.utils.js.map +1 -1
  23. package/package.json +26 -26
@@ -1,5 +1,6 @@
1
1
  import { CronAddOptions } from "../../types/cli.types.js";
2
2
  import { CronJobView } from "../../utils/cron/cron-job.utils.js";
3
+ import { AutomationManager } from "@nextclaw/kernel";
3
4
  import { CronCreateRequest } from "@nextclaw/server";
4
5
 
5
6
  //#region src/services/cron/cron-local.service.d.ts
@@ -9,7 +10,7 @@ declare function createCronCreateRequest(opts: CronAddOptions): {
9
10
  };
10
11
  declare class CronLocalService {
11
12
  private readonly automation;
12
- constructor(automation?: any);
13
+ constructor(automation?: AutomationManager);
13
14
  readonly list: (all: boolean) => CronJobView[];
14
15
  readonly addRequest: (request: CronCreateRequest) => CronJobView;
15
16
  readonly add: (opts: CronAddOptions) => {
@@ -1 +1 @@
1
- {"version":3,"file":"cron-local.service.d.ts","names":[],"sources":["../../../src/services/cron/cron-local.service.ts"],"mappings":";;;;;iBAwCgB,uBAAA,CAAwB,IAAA,EAAM,cAAA;EAAmB,OAAA,GAAU,iBAAA;EAAmB,KAAA;AAAA;AAAA,cAqBjF,gBAAA;EAAA,iBAEQ,UAAA;cAAA,UAAA;EAAA,SAKV,IAAA,GAAQ,GAAA,cAAe,WAAA;EAAA,SAIvB,UAAA,GAAc,OAAA,EAAS,iBAAA,KAAoB,WAAA;EAAA,SAW3C,GAAA,GAAO,IAAA,EAAM,cAAA;IAAmB,GAAA,EAAK,WAAA;IAAoB,KAAA;EAAA;EAAA,SAQzD,MAAA,GAAU,KAAA;EAAA,SAIV,MAAA,GAAU,KAAA,UAAe,OAAA,cAAmB,WAAA;EAAA,SAI5C,GAAA,GAAa,KAAA,UAAe,KAAA,cAAiB,OAAA;AAAA"}
1
+ {"version":3,"file":"cron-local.service.d.ts","names":[],"sources":["../../../src/services/cron/cron-local.service.ts"],"mappings":";;;;;;iBAwCgB,uBAAA,CAAwB,IAAA,EAAM,cAAA;EAAmB,OAAA,GAAU,iBAAA;EAAmB,KAAA;AAAA;AAAA,cAqBjF,gBAAA;EAAA,iBAEQ,UAAA;cAAA,UAAA,GAAU,iBAAA;EAAA,SAKpB,IAAA,GAAQ,GAAA,cAAe,WAAA;EAAA,SAIvB,UAAA,GAAc,OAAA,EAAS,iBAAA,KAAoB,WAAA;EAAA,SAW3C,GAAA,GAAO,IAAA,EAAM,cAAA;IAAmB,GAAA,EAAK,WAAA;IAAoB,KAAA;EAAA;EAAA,SAQzD,MAAA,GAAU,KAAA;EAAA,SAIV,MAAA,GAAU,KAAA,UAAe,OAAA,cAAmB,WAAA;EAAA,SAI5C,GAAA,GAAa,KAAA,UAAe,KAAA,cAAiB,OAAA;AAAA"}
@@ -1,3 +1,4 @@
1
+ import * as _$_nextclaw_kernel0 from "@nextclaw/kernel";
1
2
  import { LocalizedTextMap } from "@nextclaw/kernel";
2
3
 
3
4
  //#region src/services/marketplace/skills-query.service.d.ts
@@ -72,11 +73,11 @@ declare class SkillsQueryService {
72
73
  workdir: string;
73
74
  query?: string;
74
75
  scope?: string;
75
- }) => any;
76
+ }) => _$_nextclaw_kernel0.InstalledSkillsList;
76
77
  getInstalledInfo: (params: {
77
78
  workdir: string;
78
79
  selector: string;
79
- }) => any;
80
+ }) => _$_nextclaw_kernel0.InstalledSkillDetail;
80
81
  searchMarketplaceSkills: (params: {
81
82
  apiBaseUrl?: string;
82
83
  query?: string;
@@ -103,6 +104,7 @@ declare class SkillsQueryService {
103
104
  private normalizeRequiredString;
104
105
  private normalizeOptionalString;
105
106
  private fetchMarketplaceView;
107
+ private fetchMarketplaceViewFromBase;
106
108
  }
107
109
  //#endregion
108
110
  export { MarketplaceSkillInfoView, MarketplaceSkillsRecommendationResultView, MarketplaceSkillsSearchView, SkillsQueryService };
@@ -1 +1 @@
1
- {"version":3,"file":"skills-query.service.d.ts","names":[],"sources":["../../../src/services/marketplace/skills-query.service.ts"],"mappings":";;;KAQK,oBAAA;AAAA,KACA,2BAAA;AAAA,KAEA,sBAAA;EACH,IAAA,EAAM,2BAAA;EACN,IAAA;EACA,OAAA;AAAA;AAAA,KAGG,2BAAA;EACH,EAAA;EACA,IAAA;EACA,IAAA;EACA,IAAA;EACA,OAAA;EACA,WAAA,EAAa,gBAAA;EACb,IAAA;EACA,MAAA;EACA,OAAA,EAAS,sBAAA;EACT,SAAA;AAAA;AAAA,KAGG,wBAAA,GAA2B,2BAAA;EAC9B,WAAA;EACA,eAAA,GAAkB,gBAAA;EAClB,UAAA;EACA,QAAA;EACA,WAAA;AAAA;AAAA,KAGG,2BAAA;EACH,IAAA;EACA,IAAA;EACA,IAAA;EACA,OAAA,EAAS,sBAAA;EACT,MAAA;EACA,GAAA;EACA,WAAA;EACA,OAAA;EACA,SAAA;AAAA;AAAA,KAGG,wBAAA;EACH,KAAA;EACA,IAAA;EACA,QAAA;EACA,UAAA;EACA,IAAA,EAAM,oBAAA;EACN,KAAA;EACA,KAAA,EAAO,2BAAA;AAAA;AAAA,KAGJ,kCAAA;EACH,IAAA;EACA,OAAA;EACA,KAAA;EACA,WAAA;EACA,KAAA;EACA,KAAA,EAAO,2BAAA;AAAA;AAAA,KAGG,2BAAA,GAA8B,wBAAA;EACxC,UAAA;AAAA;AAAA,KAGU,wBAAA;EACV,UAAA;EACA,IAAA,EAAM,wBAAA;EACN,OAAA,EAAS,2BAAA;EACT,wBAAA;AAAA;AAAA,KAGU,yCAAA,GAA4C,kCAAA;EACtD,UAAA;AAAA;AAAA,cAGW,kBAAA;EACX,aAAA,GAAiB,MAAA;IACf,OAAA;IACA,KAAA;IACA,KAAA;EAAA;EAQF,gBAAA,GAAoB,MAAA;IAClB,OAAA;IACA,QAAA;EAAA;EAUF,uBAAA,GAAiC,MAAA;IAC/B,UAAA;IACA,KAAA;IACA,GAAA;IACA,IAAA;IACA,IAAA;IACA,QAAA;EAAA,MACE,OAAA,CAAQ,2BAAA;EAsBZ,uBAAA,GAAiC,MAAA;IAC/B,UAAA;IACA,IAAA;EAAA,MACE,OAAA,CAAQ,wBAAA;EA6BZ,0BAAA,GAAoC,MAAA;IAClC,UAAA;IACA,KAAA;IACA,KAAA;EAAA,MACE,OAAA,CAAQ,yCAAA;EAAA,QAkBJ,2BAAA;EAAA,QAOA,wBAAA;EAAA,QAOA,2BAAA;EAAA,QAOA,+BAAA;EAAA,QAQA,wBAAA;EAAA,QAWA,wBAAA;EAAA,QAWA,uBAAA;EAAA,QAQA,uBAAA;EAAA,QAQA,oBAAA;AAAA"}
1
+ {"version":3,"file":"skills-query.service.d.ts","names":[],"sources":["../../../src/services/marketplace/skills-query.service.ts"],"mappings":";;;;KAaK,oBAAA;AAAA,KACA,2BAAA;AAAA,KAEA,sBAAA;EACH,IAAA,EAAM,2BAAA;EACN,IAAA;EACA,OAAA;AAAA;AAAA,KAGG,2BAAA;EACH,EAAA;EACA,IAAA;EACA,IAAA;EACA,IAAA;EACA,OAAA;EACA,WAAA,EAAa,gBAAA;EACb,IAAA;EACA,MAAA;EACA,OAAA,EAAS,sBAAA;EACT,SAAA;AAAA;AAAA,KAGG,wBAAA,GAA2B,2BAAA;EAC9B,WAAA;EACA,eAAA,GAAkB,gBAAA;EAClB,UAAA;EACA,QAAA;EACA,WAAA;AAAA;AAAA,KAGG,2BAAA;EACH,IAAA;EACA,IAAA;EACA,IAAA;EACA,OAAA,EAAS,sBAAA;EACT,MAAA;EACA,GAAA;EACA,WAAA;EACA,OAAA;EACA,SAAA;AAAA;AAAA,KAGG,wBAAA;EACH,KAAA;EACA,IAAA;EACA,QAAA;EACA,UAAA;EACA,IAAA,EAAM,oBAAA;EACN,KAAA;EACA,KAAA,EAAO,2BAAA;AAAA;AAAA,KAGJ,kCAAA;EACH,IAAA;EACA,OAAA;EACA,KAAA;EACA,WAAA;EACA,KAAA;EACA,KAAA,EAAO,2BAAA;AAAA;AAAA,KAGG,2BAAA,GAA8B,wBAAA;EACxC,UAAA;AAAA;AAAA,KAGU,wBAAA;EACV,UAAA;EACA,IAAA,EAAM,wBAAA;EACN,OAAA,EAAS,2BAAA;EACT,wBAAA;AAAA;AAAA,KAGU,yCAAA,GAA4C,kCAAA;EACtD,UAAA;AAAA;AAAA,cAGW,kBAAA;EACX,aAAA,GAAiB,MAAA;IACf,OAAA;IACA,KAAA;IACA,KAAA;EAAA,MAJ2B,mBAAA,CAK5B,mBAAA;EAOD,gBAAA,GAAoB,MAAA;IAClB,OAAA;IACA,QAAA;EAAA,MATD,mBAAA,CAUA,oBAAA;EASD,uBAAA,GAAiC,MAAA;IAC/B,UAAA;IACA,KAAA;IACA,GAAA;IACA,IAAA;IACA,IAAA;IACA,QAAA;EAAA,MACE,OAAA,CAAQ,2BAAA;EAqBZ,uBAAA,GAAiC,MAAA;IAC/B,UAAA;IACA,IAAA;EAAA,MACE,OAAA,CAAQ,wBAAA;EA8BZ,0BAAA,GAAoC,MAAA;IAClC,UAAA;IACA,KAAA;IACA,KAAA;EAAA,MACE,OAAA,CAAQ,yCAAA;EAAA,QAiBJ,2BAAA;EAAA,QAOA,wBAAA;EAAA,QAOA,2BAAA;EAAA,QAOA,+BAAA;EAAA,QAQA,wBAAA;EAAA,QAWA,wBAAA;EAAA,QAWA,uBAAA;EAAA,QAQA,uBAAA;EAAA,QAQA,oBAAA;EAAA,QAwBA,4BAAA;AAAA"}
@@ -1,5 +1,6 @@
1
1
  import { runWithMarketplaceNetworkRetry } from "../../utils/marketplace/marketplace-network-retry.utils.js";
2
- import { readMarketplaceEnvelope, resolveMarketplaceApiBase } from "../../utils/marketplace/marketplace-client.utils.js";
2
+ import { MarketplaceRequestError, getMarketplaceReadFetchOptions, resolveMarketplaceReadApiBases, shouldFallbackMarketplaceReadError } from "../../utils/marketplace/marketplace-read-source.utils.js";
3
+ import { readMarketplaceEnvelope } from "../../utils/marketplace/marketplace-client.utils.js";
3
4
  import { SkillManager } from "@nextclaw/kernel";
4
5
  import { resolve } from "node:path";
5
6
  //#region src/services/marketplace/skills-query.service.ts
@@ -17,9 +18,8 @@ var SkillsQueryService = class {
17
18
  };
18
19
  searchMarketplaceSkills = async (params) => {
19
20
  const { apiBaseUrl: rawApiBaseUrl, page, pageSize, query, sort, tag } = params;
20
- const apiBaseUrl = resolveMarketplaceApiBase(rawApiBaseUrl);
21
21
  const result = await this.fetchMarketplaceView({
22
- apiBaseUrl,
22
+ apiBaseUrls: resolveMarketplaceReadApiBases(rawApiBaseUrl),
23
23
  path: "/api/v1/skills/items",
24
24
  query: {
25
25
  q: this.normalizeOptionalString(query) ?? void 0,
@@ -30,40 +30,40 @@ var SkillsQueryService = class {
30
30
  }
31
31
  });
32
32
  return {
33
- apiBaseUrl,
34
- ...result,
35
- items: result.items.map((item) => this.normalizeMarketplaceSummary(item))
33
+ apiBaseUrl: result.apiBaseUrl,
34
+ ...result.data,
35
+ items: result.data.items.map((item) => this.normalizeMarketplaceSummary(item))
36
36
  };
37
37
  };
38
38
  getMarketplaceSkillInfo = async (params) => {
39
39
  const slug = this.normalizeRequiredString(params.slug, "skill slug");
40
- const apiBaseUrl = resolveMarketplaceApiBase(params.apiBaseUrl);
40
+ const apiBaseUrls = resolveMarketplaceReadApiBases(params.apiBaseUrl);
41
41
  const encodedSlug = encodeURIComponent(slug);
42
- const item = await this.fetchMarketplaceView({
43
- apiBaseUrl,
42
+ const itemResult = await this.fetchMarketplaceView({
43
+ apiBaseUrls,
44
44
  path: `/api/v1/skills/items/${encodedSlug}`
45
45
  });
46
46
  let content = null;
47
47
  let contentUnavailableReason = null;
48
48
  try {
49
- content = this.normalizeMarketplaceContent(await this.fetchMarketplaceView({
50
- apiBaseUrl,
49
+ const contentResult = await this.fetchMarketplaceView({
50
+ apiBaseUrls,
51
51
  path: `/api/v1/skills/items/${encodedSlug}/content`
52
- }));
52
+ });
53
+ content = this.normalizeMarketplaceContent(contentResult.data);
53
54
  } catch (error) {
54
55
  contentUnavailableReason = error instanceof Error ? error.message : String(error);
55
56
  }
56
57
  return {
57
- apiBaseUrl,
58
- item: this.normalizeMarketplaceItem(item),
58
+ apiBaseUrl: itemResult.apiBaseUrl,
59
+ item: this.normalizeMarketplaceItem(itemResult.data),
59
60
  content,
60
61
  contentUnavailableReason
61
62
  };
62
63
  };
63
64
  recommendMarketplaceSkills = async (params) => {
64
- const apiBaseUrl = resolveMarketplaceApiBase(params.apiBaseUrl);
65
65
  const result = await this.fetchMarketplaceView({
66
- apiBaseUrl,
66
+ apiBaseUrls: resolveMarketplaceReadApiBases(params.apiBaseUrl),
67
67
  path: "/api/v1/skills/recommendations",
68
68
  query: {
69
69
  scene: this.normalizeOptionalString(params.scene) ?? void 0,
@@ -71,9 +71,9 @@ var SkillsQueryService = class {
71
71
  }
72
72
  });
73
73
  return {
74
- apiBaseUrl,
75
- ...result,
76
- items: result.items.map((item) => this.normalizeMarketplaceSummary(item))
74
+ apiBaseUrl: result.apiBaseUrl,
75
+ ...result.data,
76
+ items: result.data.items.map((item) => this.normalizeMarketplaceSummary(item))
77
77
  };
78
78
  };
79
79
  normalizeMarketplaceSummary = (item) => ({
@@ -115,14 +115,33 @@ var SkillsQueryService = class {
115
115
  return trimmed.length > 0 ? trimmed : null;
116
116
  };
117
117
  fetchMarketplaceView = async (params) => {
118
- const url = new URL(params.path, `${params.apiBaseUrl}/`);
119
- for (const [key, value] of Object.entries(params.query ?? {})) if (typeof value === "string" && value.length > 0) url.searchParams.set(key, value);
120
- const response = await runWithMarketplaceNetworkRetry(async () => await fetch(url.toString(), { headers: { Accept: "application/json" } }));
121
- const payload = await readMarketplaceEnvelope(response);
122
- if (!payload.ok || !payload.data) {
123
- const message = payload.error?.message || `marketplace request failed: ${response.status}`;
124
- throw new Error(message);
118
+ let lastError;
119
+ for (const apiBaseUrl of params.apiBaseUrls) try {
120
+ return {
121
+ apiBaseUrl,
122
+ data: await this.fetchMarketplaceViewFromBase({
123
+ apiBaseUrl,
124
+ path: params.path,
125
+ query: params.query
126
+ })
127
+ };
128
+ } catch (error) {
129
+ lastError = error;
130
+ if (!shouldFallbackMarketplaceReadError(error)) throw error;
125
131
  }
132
+ throw lastError;
133
+ };
134
+ fetchMarketplaceViewFromBase = async (params) => {
135
+ const { apiBaseUrl, path, query } = params;
136
+ const url = new URL(path, `${apiBaseUrl}/`);
137
+ for (const [key, value] of Object.entries(query ?? {})) if (typeof value === "string" && value.length > 0) url.searchParams.set(key, value);
138
+ const fetchOptions = getMarketplaceReadFetchOptions(apiBaseUrl);
139
+ const response = await runWithMarketplaceNetworkRetry(async () => await fetch(url.toString(), {
140
+ headers: { Accept: "application/json" },
141
+ signal: AbortSignal.timeout(fetchOptions.timeoutMs)
142
+ }), { attempts: fetchOptions.retryAttempts });
143
+ const payload = await readMarketplaceEnvelope(response);
144
+ if (!payload.ok || !payload.data) throw new MarketplaceRequestError(payload.error?.message || `marketplace request failed: ${response.status}`, response.status);
126
145
  return payload.data;
127
146
  };
128
147
  };
@@ -1 +1 @@
1
- {"version":3,"file":"skills-query.service.js","names":[],"sources":["../../../src/services/marketplace/skills-query.service.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport {\n SkillManager,\n type LocalizedTextMap,\n} from \"@nextclaw/kernel\";\nimport { readMarketplaceEnvelope, resolveMarketplaceApiBase } from \"@nextclaw-service/utils/marketplace/marketplace-client.utils.js\";\nimport { runWithMarketplaceNetworkRetry } from \"@nextclaw-service/utils/marketplace/marketplace-network-retry.utils.js\";\n\ntype MarketplaceSkillSort = \"relevance\" | \"updated\";\ntype MarketplaceSkillInstallKind = \"builtin\" | \"marketplace\";\n\ntype MarketplaceInstallSpec = {\n kind: MarketplaceSkillInstallKind;\n spec: string;\n command: string;\n};\n\ntype MarketplaceSkillItemSummary = {\n id: string;\n slug: string;\n type: \"skill\";\n name: string;\n summary: string;\n summaryI18n: LocalizedTextMap;\n tags: string[];\n author: string;\n install: MarketplaceInstallSpec;\n updatedAt: string;\n};\n\ntype MarketplaceSkillItemView = MarketplaceSkillItemSummary & {\n description?: string;\n descriptionI18n?: LocalizedTextMap;\n sourceRepo?: string;\n homepage?: string;\n publishedAt: string;\n};\n\ntype MarketplaceSkillContentView = {\n type: \"skill\";\n slug: string;\n name: string;\n install: MarketplaceInstallSpec;\n source: \"builtin\" | \"marketplace\" | \"remote\";\n raw: string;\n metadataRaw?: string;\n bodyRaw: string;\n sourceUrl?: string;\n};\n\ntype MarketplaceSkillListView = {\n total: number;\n page: number;\n pageSize: number;\n totalPages: number;\n sort: MarketplaceSkillSort;\n query?: string;\n items: MarketplaceSkillItemSummary[];\n};\n\ntype MarketplaceSkillRecommendationView = {\n type: \"skill\";\n sceneId: string;\n title: string;\n description?: string;\n total: number;\n items: MarketplaceSkillItemSummary[];\n};\n\nexport type MarketplaceSkillsSearchView = MarketplaceSkillListView & {\n apiBaseUrl: string;\n};\n\nexport type MarketplaceSkillInfoView = {\n apiBaseUrl: string;\n item: MarketplaceSkillItemView;\n content: MarketplaceSkillContentView | null;\n contentUnavailableReason: string | null;\n};\n\nexport type MarketplaceSkillsRecommendationResultView = MarketplaceSkillRecommendationView & {\n apiBaseUrl: string;\n};\n\nexport class SkillsQueryService {\n listInstalled = (params: {\n workdir: string;\n query?: string;\n scope?: string;\n }) => {\n return new SkillManager({ workspace: resolve(params.workdir) }).listInstalledSkills({\n scope: params.scope,\n query: params.query,\n });\n };\n\n getInstalledInfo = (params: {\n workdir: string;\n selector: string;\n }) => {\n const skillManager = new SkillManager({ workspace: resolve(params.workdir) });\n const detail = skillManager.getInstalledSkillDetail(params.selector);\n if (!detail) {\n throw new Error(`Installed skill not found: ${params.selector}`);\n }\n return detail;\n };\n\n searchMarketplaceSkills = async (params: {\n apiBaseUrl?: string;\n query?: string;\n tag?: string;\n sort?: string;\n page?: string | number;\n pageSize?: string | number;\n }): Promise<MarketplaceSkillsSearchView> => {\n const { apiBaseUrl: rawApiBaseUrl, page, pageSize, query, sort, tag } = params;\n const apiBaseUrl = resolveMarketplaceApiBase(rawApiBaseUrl);\n const result = await this.fetchMarketplaceView<MarketplaceSkillListView>({\n apiBaseUrl,\n path: \"/api/v1/skills/items\",\n query: {\n q: this.normalizeOptionalString(query) ?? undefined,\n tag: this.normalizeOptionalString(tag) ?? undefined,\n sort: this.normalizeMarketplaceSort(sort),\n page: this.normalizePositiveInteger(page),\n pageSize: this.normalizePositiveInteger(pageSize),\n },\n });\n\n return {\n apiBaseUrl,\n ...result,\n items: result.items.map((item) => this.normalizeMarketplaceSummary(item)),\n };\n };\n\n getMarketplaceSkillInfo = async (params: {\n apiBaseUrl?: string;\n slug: string;\n }): Promise<MarketplaceSkillInfoView> => {\n const slug = this.normalizeRequiredString(params.slug, \"skill slug\");\n const apiBaseUrl = resolveMarketplaceApiBase(params.apiBaseUrl);\n const encodedSlug = encodeURIComponent(slug);\n\n const item = await this.fetchMarketplaceView<MarketplaceSkillItemView>({\n apiBaseUrl,\n path: `/api/v1/skills/items/${encodedSlug}`,\n });\n\n let content: MarketplaceSkillContentView | null = null;\n let contentUnavailableReason: string | null = null;\n try {\n content = this.normalizeMarketplaceContent(await this.fetchMarketplaceView<MarketplaceSkillContentView>({\n apiBaseUrl,\n path: `/api/v1/skills/items/${encodedSlug}/content`,\n }));\n } catch (error) {\n contentUnavailableReason = error instanceof Error ? error.message : String(error);\n }\n\n return {\n apiBaseUrl,\n item: this.normalizeMarketplaceItem(item),\n content,\n contentUnavailableReason,\n };\n };\n\n recommendMarketplaceSkills = async (params: {\n apiBaseUrl?: string;\n scene?: string;\n limit?: string | number;\n }): Promise<MarketplaceSkillsRecommendationResultView> => {\n const apiBaseUrl = resolveMarketplaceApiBase(params.apiBaseUrl);\n const result = await this.fetchMarketplaceView<MarketplaceSkillRecommendationView>({\n apiBaseUrl,\n path: \"/api/v1/skills/recommendations\",\n query: {\n scene: this.normalizeOptionalString(params.scene) ?? undefined,\n limit: this.normalizePositiveInteger(params.limit),\n },\n });\n\n return {\n apiBaseUrl,\n ...result,\n items: result.items.map((item) => this.normalizeMarketplaceSummary(item)),\n };\n };\n\n private normalizeMarketplaceSummary = (\n item: MarketplaceSkillItemSummary,\n ): MarketplaceSkillItemSummary => ({\n ...item,\n install: this.normalizeMarketplaceInstallSpec(item.install, item.slug),\n });\n\n private normalizeMarketplaceItem = (\n item: MarketplaceSkillItemView,\n ): MarketplaceSkillItemView => ({\n ...item,\n install: this.normalizeMarketplaceInstallSpec(item.install, item.slug),\n });\n\n private normalizeMarketplaceContent = (\n content: MarketplaceSkillContentView,\n ): MarketplaceSkillContentView => ({\n ...content,\n install: this.normalizeMarketplaceInstallSpec(content.install, content.slug),\n });\n\n private normalizeMarketplaceInstallSpec = (\n install: MarketplaceInstallSpec,\n slug: string,\n ): MarketplaceInstallSpec => ({\n ...install,\n command: `nextclaw marketplace skills install ${slug}`,\n });\n\n private normalizeMarketplaceSort = (value: string | undefined): MarketplaceSkillSort | undefined => {\n const normalized = this.normalizeOptionalString(value);\n if (!normalized) {\n return undefined;\n }\n if (normalized === \"relevance\" || normalized === \"updated\") {\n return normalized;\n }\n throw new Error(`Invalid marketplace sort: ${value}. Expected relevance or updated.`);\n };\n\n private normalizePositiveInteger = (value: string | number | undefined): string | undefined => {\n if (value === undefined) {\n return undefined;\n }\n const parsed = Number(value);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new Error(`Expected a positive integer, received: ${String(value)}`);\n }\n return String(Math.floor(parsed));\n };\n\n private normalizeRequiredString = (value: string, label: string): string => {\n const normalized = this.normalizeOptionalString(value);\n if (!normalized) {\n throw new Error(`Missing ${label}`);\n }\n return normalized;\n };\n\n private normalizeOptionalString = (value: string | undefined): string | null => {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n };\n\n private fetchMarketplaceView = async <T>(params: {\n apiBaseUrl: string;\n path: string;\n query?: Record<string, string | undefined>;\n }): Promise<T> => {\n const url = new URL(params.path, `${params.apiBaseUrl}/`);\n for (const [key, value] of Object.entries(params.query ?? {})) {\n if (typeof value === \"string\" && value.length > 0) {\n url.searchParams.set(key, value);\n }\n }\n\n const response = await runWithMarketplaceNetworkRetry(async () =>\n await fetch(url.toString(), {\n headers: {\n Accept: \"application/json\",\n },\n })\n );\n\n const payload = await readMarketplaceEnvelope<T>(response);\n if (!payload.ok || !payload.data) {\n const message = payload.error?.message || `marketplace request failed: ${response.status}`;\n throw new Error(message);\n }\n\n return payload.data;\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"skills-query.service.js","names":[],"sources":["../../../src/services/marketplace/skills-query.service.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport {\n SkillManager,\n type LocalizedTextMap,\n} from \"@nextclaw/kernel\";\nimport { readMarketplaceEnvelope, resolveMarketplaceReadApiBases } from \"@nextclaw-service/utils/marketplace/marketplace-client.utils.js\";\nimport {\n getMarketplaceReadFetchOptions,\n MarketplaceRequestError,\n shouldFallbackMarketplaceReadError\n} from \"@nextclaw-service/utils/marketplace/marketplace-read-source.utils.js\";\nimport { runWithMarketplaceNetworkRetry } from \"@nextclaw-service/utils/marketplace/marketplace-network-retry.utils.js\";\n\ntype MarketplaceSkillSort = \"relevance\" | \"updated\";\ntype MarketplaceSkillInstallKind = \"builtin\" | \"marketplace\";\n\ntype MarketplaceInstallSpec = {\n kind: MarketplaceSkillInstallKind;\n spec: string;\n command: string;\n};\n\ntype MarketplaceSkillItemSummary = {\n id: string;\n slug: string;\n type: \"skill\";\n name: string;\n summary: string;\n summaryI18n: LocalizedTextMap;\n tags: string[];\n author: string;\n install: MarketplaceInstallSpec;\n updatedAt: string;\n};\n\ntype MarketplaceSkillItemView = MarketplaceSkillItemSummary & {\n description?: string;\n descriptionI18n?: LocalizedTextMap;\n sourceRepo?: string;\n homepage?: string;\n publishedAt: string;\n};\n\ntype MarketplaceSkillContentView = {\n type: \"skill\";\n slug: string;\n name: string;\n install: MarketplaceInstallSpec;\n source: \"builtin\" | \"marketplace\" | \"remote\";\n raw: string;\n metadataRaw?: string;\n bodyRaw: string;\n sourceUrl?: string;\n};\n\ntype MarketplaceSkillListView = {\n total: number;\n page: number;\n pageSize: number;\n totalPages: number;\n sort: MarketplaceSkillSort;\n query?: string;\n items: MarketplaceSkillItemSummary[];\n};\n\ntype MarketplaceSkillRecommendationView = {\n type: \"skill\";\n sceneId: string;\n title: string;\n description?: string;\n total: number;\n items: MarketplaceSkillItemSummary[];\n};\n\nexport type MarketplaceSkillsSearchView = MarketplaceSkillListView & {\n apiBaseUrl: string;\n};\n\nexport type MarketplaceSkillInfoView = {\n apiBaseUrl: string;\n item: MarketplaceSkillItemView;\n content: MarketplaceSkillContentView | null;\n contentUnavailableReason: string | null;\n};\n\nexport type MarketplaceSkillsRecommendationResultView = MarketplaceSkillRecommendationView & {\n apiBaseUrl: string;\n};\n\nexport class SkillsQueryService {\n listInstalled = (params: {\n workdir: string;\n query?: string;\n scope?: string;\n }) => {\n return new SkillManager({ workspace: resolve(params.workdir) }).listInstalledSkills({\n scope: params.scope,\n query: params.query,\n });\n };\n\n getInstalledInfo = (params: {\n workdir: string;\n selector: string;\n }) => {\n const skillManager = new SkillManager({ workspace: resolve(params.workdir) });\n const detail = skillManager.getInstalledSkillDetail(params.selector);\n if (!detail) {\n throw new Error(`Installed skill not found: ${params.selector}`);\n }\n return detail;\n };\n\n searchMarketplaceSkills = async (params: {\n apiBaseUrl?: string;\n query?: string;\n tag?: string;\n sort?: string;\n page?: string | number;\n pageSize?: string | number;\n }): Promise<MarketplaceSkillsSearchView> => {\n const { apiBaseUrl: rawApiBaseUrl, page, pageSize, query, sort, tag } = params;\n const result = await this.fetchMarketplaceView<MarketplaceSkillListView>({\n apiBaseUrls: resolveMarketplaceReadApiBases(rawApiBaseUrl),\n path: \"/api/v1/skills/items\",\n query: {\n q: this.normalizeOptionalString(query) ?? undefined,\n tag: this.normalizeOptionalString(tag) ?? undefined,\n sort: this.normalizeMarketplaceSort(sort),\n page: this.normalizePositiveInteger(page),\n pageSize: this.normalizePositiveInteger(pageSize),\n },\n });\n\n return {\n apiBaseUrl: result.apiBaseUrl,\n ...result.data,\n items: result.data.items.map((item) => this.normalizeMarketplaceSummary(item)),\n };\n };\n\n getMarketplaceSkillInfo = async (params: {\n apiBaseUrl?: string;\n slug: string;\n }): Promise<MarketplaceSkillInfoView> => {\n const slug = this.normalizeRequiredString(params.slug, \"skill slug\");\n const apiBaseUrls = resolveMarketplaceReadApiBases(params.apiBaseUrl);\n const encodedSlug = encodeURIComponent(slug);\n\n const itemResult = await this.fetchMarketplaceView<MarketplaceSkillItemView>({\n apiBaseUrls,\n path: `/api/v1/skills/items/${encodedSlug}`,\n });\n\n let content: MarketplaceSkillContentView | null = null;\n let contentUnavailableReason: string | null = null;\n try {\n const contentResult = await this.fetchMarketplaceView<MarketplaceSkillContentView>({\n apiBaseUrls,\n path: `/api/v1/skills/items/${encodedSlug}/content`,\n });\n content = this.normalizeMarketplaceContent(contentResult.data);\n } catch (error) {\n contentUnavailableReason = error instanceof Error ? error.message : String(error);\n }\n\n return {\n apiBaseUrl: itemResult.apiBaseUrl,\n item: this.normalizeMarketplaceItem(itemResult.data),\n content,\n contentUnavailableReason,\n };\n };\n\n recommendMarketplaceSkills = async (params: {\n apiBaseUrl?: string;\n scene?: string;\n limit?: string | number;\n }): Promise<MarketplaceSkillsRecommendationResultView> => {\n const result = await this.fetchMarketplaceView<MarketplaceSkillRecommendationView>({\n apiBaseUrls: resolveMarketplaceReadApiBases(params.apiBaseUrl),\n path: \"/api/v1/skills/recommendations\",\n query: {\n scene: this.normalizeOptionalString(params.scene) ?? undefined,\n limit: this.normalizePositiveInteger(params.limit),\n },\n });\n\n return {\n apiBaseUrl: result.apiBaseUrl,\n ...result.data,\n items: result.data.items.map((item) => this.normalizeMarketplaceSummary(item)),\n };\n };\n\n private normalizeMarketplaceSummary = (\n item: MarketplaceSkillItemSummary,\n ): MarketplaceSkillItemSummary => ({\n ...item,\n install: this.normalizeMarketplaceInstallSpec(item.install, item.slug),\n });\n\n private normalizeMarketplaceItem = (\n item: MarketplaceSkillItemView,\n ): MarketplaceSkillItemView => ({\n ...item,\n install: this.normalizeMarketplaceInstallSpec(item.install, item.slug),\n });\n\n private normalizeMarketplaceContent = (\n content: MarketplaceSkillContentView,\n ): MarketplaceSkillContentView => ({\n ...content,\n install: this.normalizeMarketplaceInstallSpec(content.install, content.slug),\n });\n\n private normalizeMarketplaceInstallSpec = (\n install: MarketplaceInstallSpec,\n slug: string,\n ): MarketplaceInstallSpec => ({\n ...install,\n command: `nextclaw marketplace skills install ${slug}`,\n });\n\n private normalizeMarketplaceSort = (value: string | undefined): MarketplaceSkillSort | undefined => {\n const normalized = this.normalizeOptionalString(value);\n if (!normalized) {\n return undefined;\n }\n if (normalized === \"relevance\" || normalized === \"updated\") {\n return normalized;\n }\n throw new Error(`Invalid marketplace sort: ${value}. Expected relevance or updated.`);\n };\n\n private normalizePositiveInteger = (value: string | number | undefined): string | undefined => {\n if (value === undefined) {\n return undefined;\n }\n const parsed = Number(value);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n throw new Error(`Expected a positive integer, received: ${String(value)}`);\n }\n return String(Math.floor(parsed));\n };\n\n private normalizeRequiredString = (value: string, label: string): string => {\n const normalized = this.normalizeOptionalString(value);\n if (!normalized) {\n throw new Error(`Missing ${label}`);\n }\n return normalized;\n };\n\n private normalizeOptionalString = (value: string | undefined): string | null => {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n };\n\n private fetchMarketplaceView = async <T>(params: {\n apiBaseUrls: readonly string[];\n path: string;\n query?: Record<string, string | undefined>;\n }): Promise<{ apiBaseUrl: string; data: T }> => {\n let lastError: unknown;\n for (const apiBaseUrl of params.apiBaseUrls) {\n try {\n const data = await this.fetchMarketplaceViewFromBase<T>({\n apiBaseUrl,\n path: params.path,\n query: params.query,\n });\n return { apiBaseUrl, data };\n } catch (error) {\n lastError = error;\n if (!shouldFallbackMarketplaceReadError(error)) {\n throw error;\n }\n }\n }\n throw lastError;\n };\n\n private fetchMarketplaceViewFromBase = async <T>(params: {\n apiBaseUrl: string;\n path: string;\n query?: Record<string, string | undefined>;\n }): Promise<T> => {\n const { apiBaseUrl, path, query } = params;\n const url = new URL(path, `${apiBaseUrl}/`);\n for (const [key, value] of Object.entries(query ?? {})) {\n if (typeof value === \"string\" && value.length > 0) {\n url.searchParams.set(key, value);\n }\n }\n\n const fetchOptions = getMarketplaceReadFetchOptions(apiBaseUrl);\n const response = await runWithMarketplaceNetworkRetry(\n async () => await fetch(url.toString(), {\n headers: {\n Accept: \"application/json\",\n },\n signal: AbortSignal.timeout(fetchOptions.timeoutMs),\n }),\n { attempts: fetchOptions.retryAttempts }\n );\n\n const payload = await readMarketplaceEnvelope<T>(response);\n if (!payload.ok || !payload.data) {\n const message = payload.error?.message || `marketplace request failed: ${response.status}`;\n throw new MarketplaceRequestError(message, response.status);\n }\n\n return payload.data;\n };\n\n}\n"],"mappings":";;;;;;AAyFA,IAAa,qBAAb,MAAgC;CAC9B,iBAAiB,WAIX;AACJ,SAAO,IAAI,aAAa,EAAE,WAAW,QAAQ,OAAO,QAAQ,EAAE,CAAC,CAAC,oBAAoB;GAClF,OAAO,OAAO;GACd,OAAO,OAAO;GACf,CAAC;;CAGJ,oBAAoB,WAGd;EAEJ,MAAM,SADe,IAAI,aAAa,EAAE,WAAW,QAAQ,OAAO,QAAQ,EAAE,CAAC,CACjD,wBAAwB,OAAO,SAAS;AACpE,MAAI,CAAC,OACH,OAAM,IAAI,MAAM,8BAA8B,OAAO,WAAW;AAElE,SAAO;;CAGT,0BAA0B,OAAO,WAOW;EAC1C,MAAM,EAAE,YAAY,eAAe,MAAM,UAAU,OAAO,MAAM,QAAQ;EACxE,MAAM,SAAS,MAAM,KAAK,qBAA+C;GACvE,aAAa,+BAA+B,cAAc;GAC1D,MAAM;GACN,OAAO;IACL,GAAG,KAAK,wBAAwB,MAAM,IAAI,KAAA;IAC1C,KAAK,KAAK,wBAAwB,IAAI,IAAI,KAAA;IAC1C,MAAM,KAAK,yBAAyB,KAAK;IACzC,MAAM,KAAK,yBAAyB,KAAK;IACzC,UAAU,KAAK,yBAAyB,SAAS;IAClD;GACF,CAAC;AAEF,SAAO;GACL,YAAY,OAAO;GACnB,GAAG,OAAO;GACV,OAAO,OAAO,KAAK,MAAM,KAAK,SAAS,KAAK,4BAA4B,KAAK,CAAC;GAC/E;;CAGH,0BAA0B,OAAO,WAGQ;EACvC,MAAM,OAAO,KAAK,wBAAwB,OAAO,MAAM,aAAa;EACpE,MAAM,cAAc,+BAA+B,OAAO,WAAW;EACrE,MAAM,cAAc,mBAAmB,KAAK;EAE5C,MAAM,aAAa,MAAM,KAAK,qBAA+C;GACzE;GACA,MAAM,wBAAwB;GAC/B,CAAC;EAEJ,IAAI,UAA8C;EAClD,IAAI,2BAA0C;AAC9C,MAAI;GACF,MAAM,gBAAgB,MAAM,KAAK,qBAAkD;IACjF;IACA,MAAM,wBAAwB,YAAY;IAC3C,CAAC;AACF,aAAU,KAAK,4BAA4B,cAAc,KAAK;WACvD,OAAO;AACd,8BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;;AAGnF,SAAO;GACL,YAAY,WAAW;GACvB,MAAM,KAAK,yBAAyB,WAAW,KAAK;GACpD;GACA;GACD;;CAGH,6BAA6B,OAAO,WAIsB;EACxD,MAAM,SAAS,MAAM,KAAK,qBAAyD;GACjF,aAAa,+BAA+B,OAAO,WAAW;GAC9D,MAAM;GACN,OAAO;IACL,OAAO,KAAK,wBAAwB,OAAO,MAAM,IAAI,KAAA;IACrD,OAAO,KAAK,yBAAyB,OAAO,MAAM;IACnD;GACF,CAAC;AAEF,SAAO;GACL,YAAY,OAAO;GACnB,GAAG,OAAO;GACV,OAAO,OAAO,KAAK,MAAM,KAAK,SAAS,KAAK,4BAA4B,KAAK,CAAC;GAC/E;;CAGH,+BACE,UACiC;EACjC,GAAG;EACH,SAAS,KAAK,gCAAgC,KAAK,SAAS,KAAK,KAAK;EACvE;CAED,4BACE,UAC8B;EAC9B,GAAG;EACH,SAAS,KAAK,gCAAgC,KAAK,SAAS,KAAK,KAAK;EACvE;CAED,+BACE,aACiC;EACjC,GAAG;EACH,SAAS,KAAK,gCAAgC,QAAQ,SAAS,QAAQ,KAAK;EAC7E;CAED,mCACE,SACA,UAC4B;EAC5B,GAAG;EACH,SAAS,uCAAuC;EACjD;CAED,4BAAoC,UAAgE;EAClG,MAAM,aAAa,KAAK,wBAAwB,MAAM;AACtD,MAAI,CAAC,WACH;AAEF,MAAI,eAAe,eAAe,eAAe,UAC/C,QAAO;AAET,QAAM,IAAI,MAAM,6BAA6B,MAAM,kCAAkC;;CAGvF,4BAAoC,UAA2D;AAC7F,MAAI,UAAU,KAAA,EACZ;EAEF,MAAM,SAAS,OAAO,MAAM;AAC5B,MAAI,CAAC,OAAO,SAAS,OAAO,IAAI,UAAU,EACxC,OAAM,IAAI,MAAM,0CAA0C,OAAO,MAAM,GAAG;AAE5E,SAAO,OAAO,KAAK,MAAM,OAAO,CAAC;;CAGnC,2BAAmC,OAAe,UAA0B;EAC1E,MAAM,aAAa,KAAK,wBAAwB,MAAM;AACtD,MAAI,CAAC,WACH,OAAM,IAAI,MAAM,WAAW,QAAQ;AAErC,SAAO;;CAGT,2BAAmC,UAA6C;AAC9E,MAAI,OAAO,UAAU,SACnB,QAAO;EAET,MAAM,UAAU,MAAM,MAAM;AAC5B,SAAO,QAAQ,SAAS,IAAI,UAAU;;CAGxC,uBAA+B,OAAU,WAIO;EAC9C,IAAI;AACJ,OAAK,MAAM,cAAc,OAAO,YAC9B,KAAI;AAMF,UAAO;IAAE;IAAY,MALR,MAAM,KAAK,6BAAgC;KACtD;KACA,MAAM,OAAO;KACb,OAAO,OAAO;KACf,CAAC;IACyB;WACpB,OAAO;AACd,eAAY;AACZ,OAAI,CAAC,mCAAmC,MAAM,CAC5C,OAAM;;AAIZ,QAAM;;CAGR,+BAAuC,OAAU,WAI/B;EAChB,MAAM,EAAE,YAAY,MAAM,UAAU;EACpC,MAAM,MAAM,IAAI,IAAI,MAAM,GAAG,WAAW,GAAG;AAC3C,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,SAAS,EAAE,CAAC,CACpD,KAAI,OAAO,UAAU,YAAY,MAAM,SAAS,EAC9C,KAAI,aAAa,IAAI,KAAK,MAAM;EAIpC,MAAM,eAAe,+BAA+B,WAAW;EAC/D,MAAM,WAAW,MAAM,+BACrB,YAAY,MAAM,MAAM,IAAI,UAAU,EAAE;GACpC,SAAS,EACP,QAAQ,oBACT;GACD,QAAQ,YAAY,QAAQ,aAAa,UAAU;GACpD,CAAC,EACJ,EAAE,UAAU,aAAa,eAAe,CACzC;EAED,MAAM,UAAU,MAAM,wBAA2B,SAAS;AAC1D,MAAI,CAAC,QAAQ,MAAM,CAAC,QAAQ,KAE1B,OAAM,IAAI,wBADM,QAAQ,OAAO,WAAW,+BAA+B,SAAS,UACvC,SAAS,OAAO;AAG7D,SAAO,QAAQ"}
@@ -1,5 +1,5 @@
1
1
  //#region src/services/runtime/runtime-config-init.service.d.ts
2
- declare function initializeConfigIfMissing(configPath?: any): boolean;
2
+ declare function initializeConfigIfMissing(configPath?: string): boolean;
3
3
  //#endregion
4
4
  export { initializeConfigIfMissing };
5
5
  //# sourceMappingURL=runtime-config-init.service.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import { MarketplaceSkillInstallStateFileEntry } from "../../stores/marketplace-install-state.store.js";
2
+ import { MarketplaceReadResult, resolveMarketplaceReadApiBases } from "./marketplace-read-source.utils.js";
2
3
 
3
4
  //#region src/utils/marketplace/marketplace-client.utils.d.ts
4
5
  type MarketplaceEnvelope<T> = {
@@ -26,9 +27,13 @@ type MarketplaceSkillItem = {
26
27
  declare function resolveMarketplaceApiBase(explicitBase: string | undefined): string;
27
28
  declare function resolveMarketplaceAdminToken(explicitToken: string | undefined): string | undefined;
28
29
  declare function fetchMarketplaceSkillItem(apiBase: string, slug: string): Promise<MarketplaceSkillItem>;
30
+ declare function fetchMarketplaceSkillItemFromSources(apiBases: readonly string[], slug: string): Promise<MarketplaceReadResult<MarketplaceSkillItem>>;
29
31
  declare function fetchMarketplaceSkillFiles(apiBase: string, slug: string): Promise<{
30
32
  files: MarketplaceSkillFileManifestEntry[];
31
33
  }>;
34
+ declare function fetchMarketplaceSkillFilesFromSources(apiBases: readonly string[], slug: string): Promise<MarketplaceReadResult<{
35
+ files: MarketplaceSkillFileManifestEntry[];
36
+ }>>;
32
37
  declare function fetchMarketplaceSkillFileBlob(apiBase: string, slug: string, file: MarketplaceSkillFileManifestEntry): Promise<Buffer>;
33
38
  declare function collectMarketplaceSkillFiles(rootDir: string): Array<{
34
39
  path: string;
@@ -42,5 +47,5 @@ declare function writeMarketplaceSkillFiles(params: {
42
47
  }): Promise<MarketplaceSkillInstallStateFileEntry[]>;
43
48
  declare function readMarketplaceEnvelope<T>(response: Response): Promise<MarketplaceEnvelope<T>>;
44
49
  //#endregion
45
- export { MarketplaceSkillFileManifestEntry, MarketplaceSkillItem, collectMarketplaceSkillFiles, fetchMarketplaceSkillFileBlob, fetchMarketplaceSkillFiles, fetchMarketplaceSkillItem, readMarketplaceEnvelope, resolveMarketplaceAdminToken, resolveMarketplaceApiBase, writeMarketplaceSkillFiles };
50
+ export { MarketplaceSkillFileManifestEntry, MarketplaceSkillItem, collectMarketplaceSkillFiles, fetchMarketplaceSkillFileBlob, fetchMarketplaceSkillFiles, fetchMarketplaceSkillFilesFromSources, fetchMarketplaceSkillItem, fetchMarketplaceSkillItemFromSources, readMarketplaceEnvelope, resolveMarketplaceAdminToken, resolveMarketplaceApiBase, resolveMarketplaceReadApiBases, writeMarketplaceSkillFiles };
46
51
  //# sourceMappingURL=marketplace-client.utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"marketplace-client.utils.d.ts","names":[],"sources":["../../../src/utils/marketplace/marketplace-client.utils.ts"],"mappings":";;;KAWK,mBAAA;EACH,EAAA;EACA,IAAA,GAAO,CAAA;EACP,KAAA;IACE,IAAA;IACA,OAAA;EAAA;AAAA;AAAA,KAIC,2BAAA;AAAA,KAEO,iCAAA;EACV,IAAA;EACA,YAAA;EACA,aAAA;AAAA;AAAA,KAGU,oBAAA;EACV,IAAA;EACA,WAAA;EACA,SAAA;EACA,OAAA;IAAW,IAAA,EAAM,2BAAA;EAAA;AAAA;AAAA,iBAGH,yBAAA,CAA0B,YAAA;AAAA,iBAO1B,4BAAA,CAA6B,aAAA;AAAA,iBAKvB,yBAAA,CACpB,OAAA,UACA,IAAA,WACC,OAAA,CAAQ,oBAAA;AAAA,iBAyCW,0BAAA,CACpB,OAAA,UACA,IAAA,WACC,OAAA;EAAU,KAAA,EAAO,iCAAA;AAAA;AAAA,iBAsCE,6BAAA,CACpB,OAAA,UACA,IAAA,UACA,IAAA,EAAM,iCAAA,GACL,OAAA,CAAQ,MAAA;AAAA,iBAiBK,4BAAA,CAA6B,OAAA,WAAkB,KAAA;EAAQ,IAAA;EAAc,aAAA;AAAA;AAAA,iBA6B/D,0BAAA,CAA2B,MAAA;EAC/C,cAAA;EACA,KAAA,EAAO,iCAAA;EACP,OAAA;EACA,IAAA;AAAA,IACE,OAAA,CAAQ,qCAAA;AAAA,iBAuBU,uBAAA,GAAA,CAA2B,QAAA,EAAU,QAAA,GAAW,OAAA,CAAQ,mBAAA,CAAoB,CAAA"}
1
+ {"version":3,"file":"marketplace-client.utils.d.ts","names":[],"sources":["../../../src/utils/marketplace/marketplace-client.utils.ts"],"mappings":";;;;KAkBK,mBAAA;EACH,EAAA;EACA,IAAA,GAAO,CAAA;EACP,KAAA;IACE,IAAA;IACA,OAAA;EAAA;AAAA;AAAA,KAIC,2BAAA;AAAA,KAEO,iCAAA;EACV,IAAA;EACA,YAAA;EACA,aAAA;AAAA;AAAA,KAGU,oBAAA;EACV,IAAA;EACA,WAAA;EACA,SAAA;EACA,OAAA;IAAW,IAAA,EAAM,2BAAA;EAAA;AAAA;AAAA,iBAGH,yBAAA,CAA0B,YAAA;AAAA,iBAO1B,4BAAA,CAA6B,aAAA;AAAA,iBAKvB,yBAAA,CACpB,OAAA,UACA,IAAA,WACC,OAAA,CAAQ,oBAAA;AAAA,iBAIW,oCAAA,CACpB,QAAA,qBACA,IAAA,WACC,OAAA,CAAQ,qBAAA,CAAsB,oBAAA;AAAA,iBAkDX,0BAAA,CACpB,OAAA,UACA,IAAA,WACC,OAAA;EAAU,KAAA,EAAO,iCAAA;AAAA;AAAA,iBAIE,qCAAA,CACpB,QAAA,qBACA,IAAA,WACC,OAAA,CAAQ,qBAAA;EAAwB,KAAA,EAAO,iCAAA;AAAA;AAAA,iBA+CpB,6BAAA,CACpB,OAAA,UACA,IAAA,UACA,IAAA,EAAM,iCAAA,GACL,OAAA,CAAQ,MAAA;AAAA,iBAmBK,4BAAA,CAA6B,OAAA,WAAkB,KAAA;EAAQ,IAAA;EAAc,aAAA;AAAA;AAAA,iBA6B/D,0BAAA,CAA2B,MAAA;EAC/C,cAAA;EACA,KAAA,EAAO,iCAAA;EACP,OAAA;EACA,IAAA;AAAA,IACE,OAAA,CAAQ,qCAAA;AAAA,iBAuBU,uBAAA,GAAA,CAA2B,QAAA,EAAU,QAAA,GAAW,OAAA,CAAQ,mBAAA,CAAoB,CAAA"}
@@ -1,24 +1,31 @@
1
1
  import { runWithMarketplaceNetworkRetry } from "./marketplace-network-retry.utils.js";
2
2
  import { hashMarketplaceFileBytes, isLocalMarketplaceInstallStateFile } from "../../stores/marketplace-install-state.store.js";
3
+ import { MarketplaceRequestError, getMarketplaceReadFetchOptions, resolveMarketplaceReadApiBases, runMarketplaceReadSources } from "./marketplace-read-source.utils.js";
3
4
  import { mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
4
5
  import { dirname, isAbsolute, join, relative, resolve } from "node:path";
5
6
  //#region src/utils/marketplace/marketplace-client.utils.ts
6
- const DEFAULT_MARKETPLACE_API_BASE = "https://marketplace-api.nextclaw.io";
7
7
  function resolveMarketplaceApiBase(explicitBase) {
8
- return (explicitBase?.trim() || process.env.NEXTCLAW_MARKETPLACE_API_BASE?.trim() || DEFAULT_MARKETPLACE_API_BASE).replace(/\/+$/, "");
8
+ return (explicitBase?.trim() || process.env.NEXTCLAW_MARKETPLACE_API_BASE?.trim() || "https://marketplace-api.nextclaw.io").replace(/\/+$/, "");
9
9
  }
10
10
  function resolveMarketplaceAdminToken(explicitToken) {
11
11
  const token = explicitToken?.trim() || process.env.NEXTCLAW_MARKETPLACE_ADMIN_TOKEN?.trim();
12
12
  return token && token.length > 0 ? token : void 0;
13
13
  }
14
14
  async function fetchMarketplaceSkillItem(apiBase, slug) {
15
+ return fetchMarketplaceSkillItemFromBase(apiBase, slug);
16
+ }
17
+ async function fetchMarketplaceSkillItemFromSources(apiBases, slug) {
18
+ return runMarketplaceReadSources(apiBases, (apiBase) => fetchMarketplaceSkillItemFromBase(apiBase, slug));
19
+ }
20
+ async function fetchMarketplaceSkillItemFromBase(apiBase, slug) {
21
+ const fetchOptions = getMarketplaceReadFetchOptions(apiBase);
15
22
  return runWithMarketplaceNetworkRetry(async () => {
16
- const response = await fetch(`${apiBase}/api/v1/skills/items/${encodeURIComponent(slug)}`, { headers: { Accept: "application/json" } });
23
+ const response = await fetch(`${apiBase}/api/v1/skills/items/${encodeURIComponent(slug)}`, {
24
+ headers: { Accept: "application/json" },
25
+ signal: AbortSignal.timeout(fetchOptions.timeoutMs)
26
+ });
17
27
  const payload = await readMarketplaceEnvelope(response);
18
- if (!payload.ok || !payload.data) {
19
- const message = payload.error?.message || `marketplace skill fetch failed: ${response.status}`;
20
- throw new Error(message);
21
- }
28
+ if (!payload.ok || !payload.data) throw new MarketplaceRequestError(payload.error?.message || `marketplace skill fetch failed: ${response.status}`, response.status);
22
29
  const kind = payload.data.install?.kind;
23
30
  if (kind !== "builtin" && kind !== "marketplace") throw new Error(`Unsupported skill install kind from marketplace: ${String(kind)}`);
24
31
  return {
@@ -27,16 +34,23 @@ async function fetchMarketplaceSkillItem(apiBase, slug) {
27
34
  updatedAt: typeof payload.data.updatedAt === "string" && payload.data.updatedAt.trim() ? payload.data.updatedAt.trim() : void 0,
28
35
  install: { kind }
29
36
  };
30
- });
37
+ }, { attempts: fetchOptions.retryAttempts });
31
38
  }
32
39
  async function fetchMarketplaceSkillFiles(apiBase, slug) {
40
+ return fetchMarketplaceSkillFilesFromBase(apiBase, slug);
41
+ }
42
+ async function fetchMarketplaceSkillFilesFromSources(apiBases, slug) {
43
+ return runMarketplaceReadSources(apiBases, (apiBase) => fetchMarketplaceSkillFilesFromBase(apiBase, slug));
44
+ }
45
+ async function fetchMarketplaceSkillFilesFromBase(apiBase, slug) {
46
+ const fetchOptions = getMarketplaceReadFetchOptions(apiBase);
33
47
  return runWithMarketplaceNetworkRetry(async () => {
34
- const response = await fetch(`${apiBase}/api/v1/skills/items/${encodeURIComponent(slug)}/files`, { headers: { Accept: "application/json" } });
48
+ const response = await fetch(`${apiBase}/api/v1/skills/items/${encodeURIComponent(slug)}/files`, {
49
+ headers: { Accept: "application/json" },
50
+ signal: AbortSignal.timeout(fetchOptions.timeoutMs)
51
+ });
35
52
  const payload = await readMarketplaceEnvelope(response);
36
- if (!payload.ok || !payload.data) {
37
- const message = payload.error?.message || `marketplace skill file fetch failed: ${response.status}`;
38
- throw new Error(message);
39
- }
53
+ if (!payload.ok || !payload.data) throw new MarketplaceRequestError(payload.error?.message || `marketplace skill file fetch failed: ${response.status}`, response.status);
40
54
  if (!isRecord(payload.data) || !Array.isArray(payload.data.files)) throw new Error("Invalid marketplace skill file manifest response");
41
55
  return { files: payload.data.files.map((entry, index) => {
42
56
  if (!isRecord(entry) || typeof entry.path !== "string" || entry.path.trim().length === 0) throw new Error(`Invalid marketplace skill file manifest at index ${index}`);
@@ -45,18 +59,19 @@ async function fetchMarketplaceSkillFiles(apiBase, slug) {
45
59
  if (typeof entry.contentBase64 === "string" && entry.contentBase64.trim().length > 0) normalized.contentBase64 = entry.contentBase64.trim();
46
60
  return normalized;
47
61
  }) };
48
- });
62
+ }, { attempts: fetchOptions.retryAttempts });
49
63
  }
50
64
  async function fetchMarketplaceSkillFileBlob(apiBase, slug, file) {
51
65
  const downloadUrl = resolveSkillFileDownloadUrl(apiBase, slug, file);
66
+ const fetchOptions = getMarketplaceReadFetchOptions(apiBase);
52
67
  return runWithMarketplaceNetworkRetry(async () => {
53
- const response = await fetch(downloadUrl, { headers: { Accept: "application/octet-stream" } });
54
- if (!response.ok) {
55
- const message = extractMarketplaceErrorMessage(await response.text(), response.status) || `marketplace skill file download failed: ${response.status}`;
56
- throw new Error(message);
57
- }
68
+ const response = await fetch(downloadUrl, {
69
+ headers: { Accept: "application/octet-stream" },
70
+ signal: AbortSignal.timeout(fetchOptions.timeoutMs)
71
+ });
72
+ if (!response.ok) throw new MarketplaceRequestError(extractMarketplaceErrorMessage(await response.text(), response.status) || `marketplace skill file download failed: ${response.status}`, response.status);
58
73
  return Buffer.from(await response.arrayBuffer());
59
- });
74
+ }, { attempts: fetchOptions.retryAttempts });
60
75
  }
61
76
  function collectMarketplaceSkillFiles(rootDir) {
62
77
  const output = [];
@@ -132,6 +147,6 @@ function isRecord(value) {
132
147
  return typeof value === "object" && value !== null && !Array.isArray(value);
133
148
  }
134
149
  //#endregion
135
- export { collectMarketplaceSkillFiles, fetchMarketplaceSkillFileBlob, fetchMarketplaceSkillFiles, fetchMarketplaceSkillItem, readMarketplaceEnvelope, resolveMarketplaceAdminToken, resolveMarketplaceApiBase, writeMarketplaceSkillFiles };
150
+ export { collectMarketplaceSkillFiles, fetchMarketplaceSkillFileBlob, fetchMarketplaceSkillFiles, fetchMarketplaceSkillFilesFromSources, fetchMarketplaceSkillItem, fetchMarketplaceSkillItemFromSources, readMarketplaceEnvelope, resolveMarketplaceAdminToken, resolveMarketplaceApiBase, resolveMarketplaceReadApiBases, writeMarketplaceSkillFiles };
136
151
 
137
152
  //# sourceMappingURL=marketplace-client.utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"marketplace-client.utils.js","names":[],"sources":["../../../src/utils/marketplace/marketplace-client.utils.ts"],"sourcesContent":["import { mkdirSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { runWithMarketplaceNetworkRetry } from \"@nextclaw-service/utils/marketplace/marketplace-network-retry.utils.js\";\nimport {\n hashMarketplaceFileBytes,\n isLocalMarketplaceInstallStateFile,\n type MarketplaceSkillInstallStateFileEntry\n} from \"@nextclaw-service/stores/marketplace-install-state.store.js\";\n\nconst DEFAULT_MARKETPLACE_API_BASE = \"https://marketplace-api.nextclaw.io\";\n\ntype MarketplaceEnvelope<T> = {\n ok: boolean;\n data?: T;\n error?: {\n code?: string;\n message?: string;\n };\n};\n\ntype MarketplaceSkillInstallKind = \"builtin\" | \"marketplace\";\n\nexport type MarketplaceSkillFileManifestEntry = {\n path: string;\n downloadPath?: string;\n contentBase64?: string;\n};\n\nexport type MarketplaceSkillItem = {\n slug: string;\n packageName?: string;\n updatedAt?: string;\n install: { kind: MarketplaceSkillInstallKind };\n};\n\nexport function resolveMarketplaceApiBase(explicitBase: string | undefined): string {\n const raw = explicitBase?.trim()\n || process.env.NEXTCLAW_MARKETPLACE_API_BASE?.trim()\n || DEFAULT_MARKETPLACE_API_BASE;\n return raw.replace(/\\/+$/, \"\");\n}\n\nexport function resolveMarketplaceAdminToken(explicitToken: string | undefined): string | undefined {\n const token = explicitToken?.trim() || process.env.NEXTCLAW_MARKETPLACE_ADMIN_TOKEN?.trim();\n return token && token.length > 0 ? token : undefined;\n}\n\nexport async function fetchMarketplaceSkillItem(\n apiBase: string,\n slug: string\n): Promise<MarketplaceSkillItem> {\n return runWithMarketplaceNetworkRetry(async () => {\n const response = await fetch(`${apiBase}/api/v1/skills/items/${encodeURIComponent(slug)}`, {\n headers: {\n Accept: \"application/json\"\n }\n });\n const payload = await readMarketplaceEnvelope<{\n slug?: string;\n packageName?: string;\n updatedAt?: string;\n install: { kind: MarketplaceSkillInstallKind | string };\n }>(response);\n\n if (!payload.ok || !payload.data) {\n const message = payload.error?.message || `marketplace skill fetch failed: ${response.status}`;\n throw new Error(message);\n }\n\n const kind = payload.data.install?.kind;\n if (kind !== \"builtin\" && kind !== \"marketplace\") {\n throw new Error(`Unsupported skill install kind from marketplace: ${String(kind)}`);\n }\n\n return {\n slug: typeof payload.data.slug === \"string\" && payload.data.slug.trim()\n ? payload.data.slug.trim()\n : slug,\n packageName: typeof payload.data.packageName === \"string\" && payload.data.packageName.trim()\n ? payload.data.packageName.trim()\n : undefined,\n updatedAt: typeof payload.data.updatedAt === \"string\" && payload.data.updatedAt.trim()\n ? payload.data.updatedAt.trim()\n : undefined,\n install: {\n kind\n }\n };\n });\n}\n\nexport async function fetchMarketplaceSkillFiles(\n apiBase: string,\n slug: string\n): Promise<{ files: MarketplaceSkillFileManifestEntry[] }> {\n return runWithMarketplaceNetworkRetry(async () => {\n const response = await fetch(`${apiBase}/api/v1/skills/items/${encodeURIComponent(slug)}/files`, {\n headers: {\n Accept: \"application/json\"\n }\n });\n\n const payload = await readMarketplaceEnvelope<{ files: unknown }>(response);\n if (!payload.ok || !payload.data) {\n const message = payload.error?.message || `marketplace skill file fetch failed: ${response.status}`;\n throw new Error(message);\n }\n\n if (!isRecord(payload.data) || !Array.isArray(payload.data.files)) {\n throw new Error(\"Invalid marketplace skill file manifest response\");\n }\n\n const files = payload.data.files.map((entry, index) => {\n if (!isRecord(entry) || typeof entry.path !== \"string\" || entry.path.trim().length === 0) {\n throw new Error(`Invalid marketplace skill file manifest at index ${index}`);\n }\n const normalized: MarketplaceSkillFileManifestEntry = {\n path: entry.path.trim()\n };\n if (typeof entry.downloadPath === \"string\" && entry.downloadPath.trim().length > 0) {\n normalized.downloadPath = entry.downloadPath.trim();\n }\n if (typeof entry.contentBase64 === \"string\" && entry.contentBase64.trim().length > 0) {\n normalized.contentBase64 = entry.contentBase64.trim();\n }\n return normalized;\n });\n\n return { files };\n });\n}\n\nexport async function fetchMarketplaceSkillFileBlob(\n apiBase: string,\n slug: string,\n file: MarketplaceSkillFileManifestEntry\n): Promise<Buffer> {\n const downloadUrl = resolveSkillFileDownloadUrl(apiBase, slug, file);\n return runWithMarketplaceNetworkRetry(async () => {\n const response = await fetch(downloadUrl, {\n headers: {\n Accept: \"application/octet-stream\"\n }\n });\n if (!response.ok) {\n const message = extractMarketplaceErrorMessage(await response.text(), response.status)\n || `marketplace skill file download failed: ${response.status}`;\n throw new Error(message);\n }\n return Buffer.from(await response.arrayBuffer());\n });\n}\n\nexport function collectMarketplaceSkillFiles(rootDir: string): Array<{ path: string; contentBase64: string }> {\n const output: Array<{ path: string; contentBase64: string }> = [];\n\n const walk = (dir: string, prefix: string): void => {\n const entries = readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const absolute = join(dir, entry.name);\n const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;\n if (entry.isDirectory()) {\n walk(absolute, relativePath);\n continue;\n }\n if (!entry.isFile()) {\n continue;\n }\n if (isLocalMarketplaceInstallStateFile(relativePath)) {\n continue;\n }\n output.push({\n path: relativePath,\n contentBase64: readFileSync(absolute).toString(\"base64\"),\n });\n }\n };\n\n walk(rootDir, \"\");\n return output;\n}\n\nexport async function writeMarketplaceSkillFiles(params: {\n destinationDir: string;\n files: MarketplaceSkillFileManifestEntry[];\n apiBase: string;\n slug: string;\n}): Promise<MarketplaceSkillInstallStateFileEntry[]> {\n const { destinationDir, files, apiBase, slug } = params;\n const writtenFiles: MarketplaceSkillInstallStateFileEntry[] = [];\n for (const file of files) {\n const targetPath = resolve(destinationDir, ...file.path.split(\"/\"));\n const rel = relative(destinationDir, targetPath);\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n throw new Error(`Invalid marketplace file path: ${file.path}`);\n }\n\n mkdirSync(dirname(targetPath), { recursive: true });\n const bytes = file.contentBase64\n ? decodeMarketplaceFileContent(file.path, file.contentBase64)\n : await fetchMarketplaceSkillFileBlob(apiBase, slug, file);\n writeFileSync(targetPath, bytes);\n writtenFiles.push({\n path: normalizeMarketplaceRelativePath(file.path),\n sha256: hashMarketplaceFileBytes(bytes),\n });\n }\n return writtenFiles;\n}\n\nexport async function readMarketplaceEnvelope<T>(response: Response): Promise<MarketplaceEnvelope<T>> {\n const raw = await response.text();\n let payload: unknown;\n try {\n payload = raw.length > 0 ? JSON.parse(raw) : null;\n } catch {\n throw new Error(`Invalid marketplace response: ${response.status}`);\n }\n\n if (!isRecord(payload) || typeof payload.ok !== \"boolean\") {\n throw new Error(`Invalid marketplace response shape: ${response.status}`);\n }\n\n return payload as MarketplaceEnvelope<T>;\n}\n\nfunction resolveSkillFileDownloadUrl(\n apiBase: string,\n slug: string,\n file: MarketplaceSkillFileManifestEntry\n): string {\n if (file.downloadPath) {\n return file.downloadPath.startsWith(\"http://\") || file.downloadPath.startsWith(\"https://\")\n ? file.downloadPath\n : `${apiBase}${file.downloadPath}`;\n }\n return `${apiBase}/api/v1/skills/items/${encodeURIComponent(slug)}/files/blob?path=${encodeURIComponent(file.path)}`;\n}\n\nfunction extractMarketplaceErrorMessage(raw: string, fallbackStatus: number): string | undefined {\n if (!raw) {\n return undefined;\n }\n try {\n const payload = JSON.parse(raw) as MarketplaceEnvelope<unknown>;\n return payload.error?.message;\n } catch {\n return raw || `Request failed (${fallbackStatus})`;\n }\n}\n\nfunction decodeMarketplaceFileContent(path: string, contentBase64: string): Buffer {\n const normalized = contentBase64.replace(/\\s+/g, \"\");\n if (!normalized || normalized.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(normalized)) {\n throw new Error(`Invalid marketplace file contentBase64 for path: ${path}`);\n }\n return Buffer.from(normalized, \"base64\");\n}\n\nfunction normalizeMarketplaceRelativePath(path: string): string {\n return path.replace(/\\\\/g, \"/\");\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":";;;;;AASA,MAAM,+BAA+B;AA0BrC,SAAgB,0BAA0B,cAA0C;AAIlF,SAHY,cAAc,MAAM,IAC3B,QAAQ,IAAI,+BAA+B,MAAM,IACjD,8BACM,QAAQ,QAAQ,GAAG;;AAGhC,SAAgB,6BAA6B,eAAuD;CAClG,MAAM,QAAQ,eAAe,MAAM,IAAI,QAAQ,IAAI,kCAAkC,MAAM;AAC3F,QAAO,SAAS,MAAM,SAAS,IAAI,QAAQ,KAAA;;AAG7C,eAAsB,0BACpB,SACA,MAC+B;AAC/B,QAAO,+BAA+B,YAAY;EAChD,MAAM,WAAW,MAAM,MAAM,GAAG,QAAQ,uBAAuB,mBAAmB,KAAK,IAAI,EACzF,SAAS,EACP,QAAQ,oBACT,EACF,CAAC;EACF,MAAM,UAAU,MAAM,wBAKnB,SAAS;AAEZ,MAAI,CAAC,QAAQ,MAAM,CAAC,QAAQ,MAAM;GAChC,MAAM,UAAU,QAAQ,OAAO,WAAW,mCAAmC,SAAS;AACtF,SAAM,IAAI,MAAM,QAAQ;;EAG1B,MAAM,OAAO,QAAQ,KAAK,SAAS;AACnC,MAAI,SAAS,aAAa,SAAS,cACjC,OAAM,IAAI,MAAM,oDAAoD,OAAO,KAAK,GAAG;AAGrF,SAAO;GACL,MAAM,OAAO,QAAQ,KAAK,SAAS,YAAY,QAAQ,KAAK,KAAK,MAAM,GACnE,QAAQ,KAAK,KAAK,MAAM,GACxB;GACJ,aAAa,OAAO,QAAQ,KAAK,gBAAgB,YAAY,QAAQ,KAAK,YAAY,MAAM,GACxF,QAAQ,KAAK,YAAY,MAAM,GAC/B,KAAA;GACJ,WAAW,OAAO,QAAQ,KAAK,cAAc,YAAY,QAAQ,KAAK,UAAU,MAAM,GAClF,QAAQ,KAAK,UAAU,MAAM,GAC7B,KAAA;GACJ,SAAS,EACP,MACD;GACF;GACD;;AAGJ,eAAsB,2BACpB,SACA,MACyD;AACzD,QAAO,+BAA+B,YAAY;EAChD,MAAM,WAAW,MAAM,MAAM,GAAG,QAAQ,uBAAuB,mBAAmB,KAAK,CAAC,SAAS,EAC/F,SAAS,EACP,QAAQ,oBACT,EACF,CAAC;EAEF,MAAM,UAAU,MAAM,wBAA4C,SAAS;AAC3E,MAAI,CAAC,QAAQ,MAAM,CAAC,QAAQ,MAAM;GAChC,MAAM,UAAU,QAAQ,OAAO,WAAW,wCAAwC,SAAS;AAC3F,SAAM,IAAI,MAAM,QAAQ;;AAG1B,MAAI,CAAC,SAAS,QAAQ,KAAK,IAAI,CAAC,MAAM,QAAQ,QAAQ,KAAK,MAAM,CAC/D,OAAM,IAAI,MAAM,mDAAmD;AAmBrE,SAAO,EAAE,OAhBK,QAAQ,KAAK,MAAM,KAAK,OAAO,UAAU;AACrD,OAAI,CAAC,SAAS,MAAM,IAAI,OAAO,MAAM,SAAS,YAAY,MAAM,KAAK,MAAM,CAAC,WAAW,EACrF,OAAM,IAAI,MAAM,oDAAoD,QAAQ;GAE9E,MAAM,aAAgD,EACpD,MAAM,MAAM,KAAK,MAAM,EACxB;AACD,OAAI,OAAO,MAAM,iBAAiB,YAAY,MAAM,aAAa,MAAM,CAAC,SAAS,EAC/E,YAAW,eAAe,MAAM,aAAa,MAAM;AAErD,OAAI,OAAO,MAAM,kBAAkB,YAAY,MAAM,cAAc,MAAM,CAAC,SAAS,EACjF,YAAW,gBAAgB,MAAM,cAAc,MAAM;AAEvD,UAAO;IACP,EAEc;GAChB;;AAGJ,eAAsB,8BACpB,SACA,MACA,MACiB;CACjB,MAAM,cAAc,4BAA4B,SAAS,MAAM,KAAK;AACpE,QAAO,+BAA+B,YAAY;EAChD,MAAM,WAAW,MAAM,MAAM,aAAa,EACxC,SAAS,EACP,QAAQ,4BACT,EACF,CAAC;AACF,MAAI,CAAC,SAAS,IAAI;GAChB,MAAM,UAAU,+BAA+B,MAAM,SAAS,MAAM,EAAE,SAAS,OAAO,IACjF,2CAA2C,SAAS;AACzD,SAAM,IAAI,MAAM,QAAQ;;AAE1B,SAAO,OAAO,KAAK,MAAM,SAAS,aAAa,CAAC;GAChD;;AAGJ,SAAgB,6BAA6B,SAAiE;CAC5G,MAAM,SAAyD,EAAE;CAEjE,MAAM,QAAQ,KAAa,WAAyB;EAClD,MAAM,UAAU,YAAY,KAAK,EAAE,eAAe,MAAM,CAAC;AACzD,OAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,WAAW,KAAK,KAAK,MAAM,KAAK;GACtC,MAAM,eAAe,SAAS,GAAG,OAAO,GAAG,MAAM,SAAS,MAAM;AAChE,OAAI,MAAM,aAAa,EAAE;AACvB,SAAK,UAAU,aAAa;AAC5B;;AAEF,OAAI,CAAC,MAAM,QAAQ,CACjB;AAEF,OAAI,mCAAmC,aAAa,CAClD;AAEF,UAAO,KAAK;IACV,MAAM;IACN,eAAe,aAAa,SAAS,CAAC,SAAS,SAAS;IACzD,CAAC;;;AAIN,MAAK,SAAS,GAAG;AACjB,QAAO;;AAGT,eAAsB,2BAA2B,QAKI;CACnD,MAAM,EAAE,gBAAgB,OAAO,SAAS,SAAS;CACjD,MAAM,eAAwD,EAAE;AAChE,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,aAAa,QAAQ,gBAAgB,GAAG,KAAK,KAAK,MAAM,IAAI,CAAC;EACnE,MAAM,MAAM,SAAS,gBAAgB,WAAW;AAChD,MAAI,IAAI,WAAW,KAAK,IAAI,WAAW,IAAI,CACzC,OAAM,IAAI,MAAM,kCAAkC,KAAK,OAAO;AAGhE,YAAU,QAAQ,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC;EACnD,MAAM,QAAQ,KAAK,gBACf,6BAA6B,KAAK,MAAM,KAAK,cAAc,GAC3D,MAAM,8BAA8B,SAAS,MAAM,KAAK;AAC5D,gBAAc,YAAY,MAAM;AAChC,eAAa,KAAK;GAChB,MAAM,iCAAiC,KAAK,KAAK;GACjD,QAAQ,yBAAyB,MAAM;GACxC,CAAC;;AAEJ,QAAO;;AAGT,eAAsB,wBAA2B,UAAqD;CACpG,MAAM,MAAM,MAAM,SAAS,MAAM;CACjC,IAAI;AACJ,KAAI;AACF,YAAU,IAAI,SAAS,IAAI,KAAK,MAAM,IAAI,GAAG;SACvC;AACN,QAAM,IAAI,MAAM,iCAAiC,SAAS,SAAS;;AAGrE,KAAI,CAAC,SAAS,QAAQ,IAAI,OAAO,QAAQ,OAAO,UAC9C,OAAM,IAAI,MAAM,uCAAuC,SAAS,SAAS;AAG3E,QAAO;;AAGT,SAAS,4BACP,SACA,MACA,MACQ;AACR,KAAI,KAAK,aACP,QAAO,KAAK,aAAa,WAAW,UAAU,IAAI,KAAK,aAAa,WAAW,WAAW,GACtF,KAAK,eACL,GAAG,UAAU,KAAK;AAExB,QAAO,GAAG,QAAQ,uBAAuB,mBAAmB,KAAK,CAAC,mBAAmB,mBAAmB,KAAK,KAAK;;AAGpH,SAAS,+BAA+B,KAAa,gBAA4C;AAC/F,KAAI,CAAC,IACH;AAEF,KAAI;AAEF,SADgB,KAAK,MAAM,IAAI,CAChB,OAAO;SAChB;AACN,SAAO,OAAO,mBAAmB,eAAe;;;AAIpD,SAAS,6BAA6B,MAAc,eAA+B;CACjF,MAAM,aAAa,cAAc,QAAQ,QAAQ,GAAG;AACpD,KAAI,CAAC,cAAc,WAAW,SAAS,MAAM,KAAK,CAAC,yBAAyB,KAAK,WAAW,CAC1F,OAAM,IAAI,MAAM,oDAAoD,OAAO;AAE7E,QAAO,OAAO,KAAK,YAAY,SAAS;;AAG1C,SAAS,iCAAiC,MAAsB;AAC9D,QAAO,KAAK,QAAQ,OAAO,IAAI;;AAGjC,SAAS,SAAS,OAAkD;AAClE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM"}
1
+ {"version":3,"file":"marketplace-client.utils.js","names":[],"sources":["../../../src/utils/marketplace/marketplace-client.utils.ts"],"sourcesContent":["import { mkdirSync, readdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { runWithMarketplaceNetworkRetry } from \"@nextclaw-service/utils/marketplace/marketplace-network-retry.utils.js\";\nimport {\n hashMarketplaceFileBytes,\n isLocalMarketplaceInstallStateFile,\n type MarketplaceSkillInstallStateFileEntry\n} from \"@nextclaw-service/stores/marketplace-install-state.store.js\";\nimport {\n DEFAULT_MARKETPLACE_API_BASE,\n getMarketplaceReadFetchOptions,\n MarketplaceRequestError,\n runMarketplaceReadSources,\n type MarketplaceReadResult\n} from \"@nextclaw-service/utils/marketplace/marketplace-read-source.utils.js\";\n\nexport { resolveMarketplaceReadApiBases } from \"@nextclaw-service/utils/marketplace/marketplace-read-source.utils.js\";\n\ntype MarketplaceEnvelope<T> = {\n ok: boolean;\n data?: T;\n error?: {\n code?: string;\n message?: string;\n };\n};\n\ntype MarketplaceSkillInstallKind = \"builtin\" | \"marketplace\";\n\nexport type MarketplaceSkillFileManifestEntry = {\n path: string;\n downloadPath?: string;\n contentBase64?: string;\n};\n\nexport type MarketplaceSkillItem = {\n slug: string;\n packageName?: string;\n updatedAt?: string;\n install: { kind: MarketplaceSkillInstallKind };\n};\n\nexport function resolveMarketplaceApiBase(explicitBase: string | undefined): string {\n const raw = explicitBase?.trim()\n || process.env.NEXTCLAW_MARKETPLACE_API_BASE?.trim()\n || DEFAULT_MARKETPLACE_API_BASE;\n return raw.replace(/\\/+$/, \"\");\n}\n\nexport function resolveMarketplaceAdminToken(explicitToken: string | undefined): string | undefined {\n const token = explicitToken?.trim() || process.env.NEXTCLAW_MARKETPLACE_ADMIN_TOKEN?.trim();\n return token && token.length > 0 ? token : undefined;\n}\n\nexport async function fetchMarketplaceSkillItem(\n apiBase: string,\n slug: string\n): Promise<MarketplaceSkillItem> {\n return fetchMarketplaceSkillItemFromBase(apiBase, slug);\n}\n\nexport async function fetchMarketplaceSkillItemFromSources(\n apiBases: readonly string[],\n slug: string,\n): Promise<MarketplaceReadResult<MarketplaceSkillItem>> {\n return runMarketplaceReadSources(apiBases, (apiBase) => fetchMarketplaceSkillItemFromBase(apiBase, slug));\n}\n\nasync function fetchMarketplaceSkillItemFromBase(\n apiBase: string,\n slug: string,\n): Promise<MarketplaceSkillItem> {\n const fetchOptions = getMarketplaceReadFetchOptions(apiBase);\n return runWithMarketplaceNetworkRetry(async () => {\n const response = await fetch(`${apiBase}/api/v1/skills/items/${encodeURIComponent(slug)}`, {\n headers: {\n Accept: \"application/json\"\n },\n signal: AbortSignal.timeout(fetchOptions.timeoutMs),\n });\n const payload = await readMarketplaceEnvelope<{\n slug?: string;\n packageName?: string;\n updatedAt?: string;\n install: { kind: MarketplaceSkillInstallKind | string };\n }>(response);\n\n if (!payload.ok || !payload.data) {\n const message = payload.error?.message || `marketplace skill fetch failed: ${response.status}`;\n throw new MarketplaceRequestError(message, response.status);\n }\n\n const kind = payload.data.install?.kind;\n if (kind !== \"builtin\" && kind !== \"marketplace\") {\n throw new Error(`Unsupported skill install kind from marketplace: ${String(kind)}`);\n }\n\n return {\n slug: typeof payload.data.slug === \"string\" && payload.data.slug.trim()\n ? payload.data.slug.trim()\n : slug,\n packageName: typeof payload.data.packageName === \"string\" && payload.data.packageName.trim()\n ? payload.data.packageName.trim()\n : undefined,\n updatedAt: typeof payload.data.updatedAt === \"string\" && payload.data.updatedAt.trim()\n ? payload.data.updatedAt.trim()\n : undefined,\n install: {\n kind\n }\n };\n }, { attempts: fetchOptions.retryAttempts });\n}\n\nexport async function fetchMarketplaceSkillFiles(\n apiBase: string,\n slug: string\n): Promise<{ files: MarketplaceSkillFileManifestEntry[] }> {\n return fetchMarketplaceSkillFilesFromBase(apiBase, slug);\n}\n\nexport async function fetchMarketplaceSkillFilesFromSources(\n apiBases: readonly string[],\n slug: string,\n): Promise<MarketplaceReadResult<{ files: MarketplaceSkillFileManifestEntry[] }>> {\n return runMarketplaceReadSources(apiBases, (apiBase) => fetchMarketplaceSkillFilesFromBase(apiBase, slug));\n}\n\nasync function fetchMarketplaceSkillFilesFromBase(\n apiBase: string,\n slug: string,\n): Promise<{ files: MarketplaceSkillFileManifestEntry[] }> {\n const fetchOptions = getMarketplaceReadFetchOptions(apiBase);\n return runWithMarketplaceNetworkRetry(async () => {\n const response = await fetch(`${apiBase}/api/v1/skills/items/${encodeURIComponent(slug)}/files`, {\n headers: {\n Accept: \"application/json\"\n },\n signal: AbortSignal.timeout(fetchOptions.timeoutMs),\n });\n\n const payload = await readMarketplaceEnvelope<{ files: unknown }>(response);\n if (!payload.ok || !payload.data) {\n const message = payload.error?.message || `marketplace skill file fetch failed: ${response.status}`;\n throw new MarketplaceRequestError(message, response.status);\n }\n\n if (!isRecord(payload.data) || !Array.isArray(payload.data.files)) {\n throw new Error(\"Invalid marketplace skill file manifest response\");\n }\n\n const files = payload.data.files.map((entry, index) => {\n if (!isRecord(entry) || typeof entry.path !== \"string\" || entry.path.trim().length === 0) {\n throw new Error(`Invalid marketplace skill file manifest at index ${index}`);\n }\n const normalized: MarketplaceSkillFileManifestEntry = {\n path: entry.path.trim()\n };\n if (typeof entry.downloadPath === \"string\" && entry.downloadPath.trim().length > 0) {\n normalized.downloadPath = entry.downloadPath.trim();\n }\n if (typeof entry.contentBase64 === \"string\" && entry.contentBase64.trim().length > 0) {\n normalized.contentBase64 = entry.contentBase64.trim();\n }\n return normalized;\n });\n\n return { files };\n }, { attempts: fetchOptions.retryAttempts });\n}\n\nexport async function fetchMarketplaceSkillFileBlob(\n apiBase: string,\n slug: string,\n file: MarketplaceSkillFileManifestEntry\n): Promise<Buffer> {\n const downloadUrl = resolveSkillFileDownloadUrl(apiBase, slug, file);\n const fetchOptions = getMarketplaceReadFetchOptions(apiBase);\n return runWithMarketplaceNetworkRetry(async () => {\n const response = await fetch(downloadUrl, {\n headers: {\n Accept: \"application/octet-stream\"\n },\n signal: AbortSignal.timeout(fetchOptions.timeoutMs),\n });\n if (!response.ok) {\n const message = extractMarketplaceErrorMessage(await response.text(), response.status)\n || `marketplace skill file download failed: ${response.status}`;\n throw new MarketplaceRequestError(message, response.status);\n }\n return Buffer.from(await response.arrayBuffer());\n }, { attempts: fetchOptions.retryAttempts });\n}\n\nexport function collectMarketplaceSkillFiles(rootDir: string): Array<{ path: string; contentBase64: string }> {\n const output: Array<{ path: string; contentBase64: string }> = [];\n\n const walk = (dir: string, prefix: string): void => {\n const entries = readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const absolute = join(dir, entry.name);\n const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;\n if (entry.isDirectory()) {\n walk(absolute, relativePath);\n continue;\n }\n if (!entry.isFile()) {\n continue;\n }\n if (isLocalMarketplaceInstallStateFile(relativePath)) {\n continue;\n }\n output.push({\n path: relativePath,\n contentBase64: readFileSync(absolute).toString(\"base64\"),\n });\n }\n };\n\n walk(rootDir, \"\");\n return output;\n}\n\nexport async function writeMarketplaceSkillFiles(params: {\n destinationDir: string;\n files: MarketplaceSkillFileManifestEntry[];\n apiBase: string;\n slug: string;\n}): Promise<MarketplaceSkillInstallStateFileEntry[]> {\n const { destinationDir, files, apiBase, slug } = params;\n const writtenFiles: MarketplaceSkillInstallStateFileEntry[] = [];\n for (const file of files) {\n const targetPath = resolve(destinationDir, ...file.path.split(\"/\"));\n const rel = relative(destinationDir, targetPath);\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n throw new Error(`Invalid marketplace file path: ${file.path}`);\n }\n\n mkdirSync(dirname(targetPath), { recursive: true });\n const bytes = file.contentBase64\n ? decodeMarketplaceFileContent(file.path, file.contentBase64)\n : await fetchMarketplaceSkillFileBlob(apiBase, slug, file);\n writeFileSync(targetPath, bytes);\n writtenFiles.push({\n path: normalizeMarketplaceRelativePath(file.path),\n sha256: hashMarketplaceFileBytes(bytes),\n });\n }\n return writtenFiles;\n}\n\nexport async function readMarketplaceEnvelope<T>(response: Response): Promise<MarketplaceEnvelope<T>> {\n const raw = await response.text();\n let payload: unknown;\n try {\n payload = raw.length > 0 ? JSON.parse(raw) : null;\n } catch {\n throw new Error(`Invalid marketplace response: ${response.status}`);\n }\n\n if (!isRecord(payload) || typeof payload.ok !== \"boolean\") {\n throw new Error(`Invalid marketplace response shape: ${response.status}`);\n }\n\n return payload as MarketplaceEnvelope<T>;\n}\n\nfunction resolveSkillFileDownloadUrl(\n apiBase: string,\n slug: string,\n file: MarketplaceSkillFileManifestEntry\n): string {\n if (file.downloadPath) {\n return file.downloadPath.startsWith(\"http://\") || file.downloadPath.startsWith(\"https://\")\n ? file.downloadPath\n : `${apiBase}${file.downloadPath}`;\n }\n return `${apiBase}/api/v1/skills/items/${encodeURIComponent(slug)}/files/blob?path=${encodeURIComponent(file.path)}`;\n}\n\nfunction extractMarketplaceErrorMessage(raw: string, fallbackStatus: number): string | undefined {\n if (!raw) {\n return undefined;\n }\n try {\n const payload = JSON.parse(raw) as MarketplaceEnvelope<unknown>;\n return payload.error?.message;\n } catch {\n return raw || `Request failed (${fallbackStatus})`;\n }\n}\n\nfunction decodeMarketplaceFileContent(path: string, contentBase64: string): Buffer {\n const normalized = contentBase64.replace(/\\s+/g, \"\");\n if (!normalized || normalized.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(normalized)) {\n throw new Error(`Invalid marketplace file contentBase64 for path: ${path}`);\n }\n return Buffer.from(normalized, \"base64\");\n}\n\nfunction normalizeMarketplaceRelativePath(path: string): string {\n return path.replace(/\\\\/g, \"/\");\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":"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"}
@@ -1,5 +1,9 @@
1
1
  //#region src/utils/marketplace/marketplace-network-retry.utils.d.ts
2
- declare function runWithMarketplaceNetworkRetry<T>(action: () => Promise<T>): Promise<T>;
2
+ type MarketplaceNetworkRetryOptions = {
3
+ attempts?: number;
4
+ baseDelayMs?: number;
5
+ };
6
+ declare function runWithMarketplaceNetworkRetry<T>(action: () => Promise<T>, options?: MarketplaceNetworkRetryOptions): Promise<T>;
3
7
  //#endregion
4
8
  export { runWithMarketplaceNetworkRetry };
5
9
  //# sourceMappingURL=marketplace-network-retry.utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"marketplace-network-retry.utils.d.ts","names":[],"sources":["../../../src/utils/marketplace/marketplace-network-retry.utils.ts"],"mappings":";iBAoCsB,8BAAA,GAAA,CAAkC,MAAA,QAAc,OAAA,CAAQ,CAAA,IAAK,OAAA,CAAQ,CAAA"}
1
+ {"version":3,"file":"marketplace-network-retry.utils.d.ts","names":[],"sources":["../../../src/utils/marketplace/marketplace-network-retry.utils.ts"],"mappings":";KAGK,8BAAA;EACH,QAAA;EACA,WAAA;AAAA;AAAA,iBAoCoB,8BAAA,GAAA,CACpB,MAAA,QAAc,OAAA,CAAQ,CAAA,GACtB,OAAA,GAAS,8BAAA,GACR,OAAA,CAAQ,CAAA"}
@@ -17,14 +17,16 @@ function isRetryableMarketplaceNetworkError(error) {
17
17
  if (error instanceof TypeError && error.message === "fetch failed") return true;
18
18
  return false;
19
19
  }
20
- async function runWithMarketplaceNetworkRetry(action) {
20
+ async function runWithMarketplaceNetworkRetry(action, options = {}) {
21
+ const attempts = options.attempts ?? MARKETPLACE_NETWORK_RETRY_ATTEMPTS;
22
+ const baseDelayMs = options.baseDelayMs ?? MARKETPLACE_NETWORK_RETRY_BASE_MS;
21
23
  let last;
22
- for (let attempt = 1; attempt <= MARKETPLACE_NETWORK_RETRY_ATTEMPTS; attempt++) try {
24
+ for (let attempt = 1; attempt <= attempts; attempt++) try {
23
25
  return await action();
24
26
  } catch (error) {
25
27
  last = error;
26
- if (attempt === MARKETPLACE_NETWORK_RETRY_ATTEMPTS || !isRetryableMarketplaceNetworkError(error)) throw error;
27
- await sleepMs(MARKETPLACE_NETWORK_RETRY_BASE_MS * 2 ** (attempt - 1));
28
+ if (attempt === attempts || !isRetryableMarketplaceNetworkError(error)) throw error;
29
+ await sleepMs(baseDelayMs * 2 ** (attempt - 1));
28
30
  }
29
31
  throw last;
30
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"marketplace-network-retry.utils.js","names":[],"sources":["../../../src/utils/marketplace/marketplace-network-retry.utils.ts"],"sourcesContent":["const MARKETPLACE_NETWORK_RETRY_ATTEMPTS = 5;\nconst MARKETPLACE_NETWORK_RETRY_BASE_MS = 350;\n\nfunction sleepMs(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nfunction isRetryableMarketplaceNetworkError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n if (error.name === \"AbortError\") {\n return false;\n }\n const cause = (error as Error & { cause?: unknown }).cause;\n if (cause && typeof cause === \"object\" && cause !== null && \"code\" in cause) {\n const code = (cause as { code?: unknown }).code;\n if (\n code === \"ECONNRESET\"\n || code === \"ECONNREFUSED\"\n || code === \"ETIMEDOUT\"\n || code === \"EPIPE\"\n || code === \"ENOTFOUND\"\n || code === \"EAI_AGAIN\"\n ) {\n return true;\n }\n }\n if (error instanceof TypeError && error.message === \"fetch failed\") {\n return true;\n }\n return false;\n}\n\nexport async function runWithMarketplaceNetworkRetry<T>(action: () => Promise<T>): Promise<T> {\n let last: unknown;\n for (let attempt = 1; attempt <= MARKETPLACE_NETWORK_RETRY_ATTEMPTS; attempt++) {\n try {\n return await action();\n } catch (error) {\n last = error;\n if (attempt === MARKETPLACE_NETWORK_RETRY_ATTEMPTS || !isRetryableMarketplaceNetworkError(error)) {\n throw error;\n }\n await sleepMs(MARKETPLACE_NETWORK_RETRY_BASE_MS * 2 ** (attempt - 1));\n }\n }\n throw last;\n}\n"],"mappings":";AAAA,MAAM,qCAAqC;AAC3C,MAAM,oCAAoC;AAE1C,SAAS,QAAQ,IAA2B;AAC1C,QAAO,IAAI,SAAS,YAAY;AAC9B,aAAW,SAAS,GAAG;GACvB;;AAGJ,SAAS,mCAAmC,OAAyB;AACnE,KAAI,EAAE,iBAAiB,OACrB,QAAO;AAET,KAAI,MAAM,SAAS,aACjB,QAAO;CAET,MAAM,QAAS,MAAsC;AACrD,KAAI,SAAS,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,OAAO;EAC3E,MAAM,OAAQ,MAA6B;AAC3C,MACE,SAAS,gBACN,SAAS,kBACT,SAAS,eACT,SAAS,WACT,SAAS,eACT,SAAS,YAEZ,QAAO;;AAGX,KAAI,iBAAiB,aAAa,MAAM,YAAY,eAClD,QAAO;AAET,QAAO;;AAGT,eAAsB,+BAAkC,QAAsC;CAC5F,IAAI;AACJ,MAAK,IAAI,UAAU,GAAG,WAAW,oCAAoC,UACnE,KAAI;AACF,SAAO,MAAM,QAAQ;UACd,OAAO;AACd,SAAO;AACP,MAAI,YAAY,sCAAsC,CAAC,mCAAmC,MAAM,CAC9F,OAAM;AAER,QAAM,QAAQ,oCAAoC,MAAM,UAAU,GAAG;;AAGzE,OAAM"}
1
+ {"version":3,"file":"marketplace-network-retry.utils.js","names":[],"sources":["../../../src/utils/marketplace/marketplace-network-retry.utils.ts"],"sourcesContent":["const MARKETPLACE_NETWORK_RETRY_ATTEMPTS = 5;\nconst MARKETPLACE_NETWORK_RETRY_BASE_MS = 350;\n\ntype MarketplaceNetworkRetryOptions = {\n attempts?: number;\n baseDelayMs?: number;\n};\n\nfunction sleepMs(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nfunction isRetryableMarketplaceNetworkError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n if (error.name === \"AbortError\") {\n return false;\n }\n const cause = (error as Error & { cause?: unknown }).cause;\n if (cause && typeof cause === \"object\" && cause !== null && \"code\" in cause) {\n const code = (cause as { code?: unknown }).code;\n if (\n code === \"ECONNRESET\"\n || code === \"ECONNREFUSED\"\n || code === \"ETIMEDOUT\"\n || code === \"EPIPE\"\n || code === \"ENOTFOUND\"\n || code === \"EAI_AGAIN\"\n ) {\n return true;\n }\n }\n if (error instanceof TypeError && error.message === \"fetch failed\") {\n return true;\n }\n return false;\n}\n\nexport async function runWithMarketplaceNetworkRetry<T>(\n action: () => Promise<T>,\n options: MarketplaceNetworkRetryOptions = {}\n): Promise<T> {\n const attempts = options.attempts ?? MARKETPLACE_NETWORK_RETRY_ATTEMPTS;\n const baseDelayMs = options.baseDelayMs ?? MARKETPLACE_NETWORK_RETRY_BASE_MS;\n let last: unknown;\n for (let attempt = 1; attempt <= attempts; attempt++) {\n try {\n return await action();\n } catch (error) {\n last = error;\n if (attempt === attempts || !isRetryableMarketplaceNetworkError(error)) {\n throw error;\n }\n await sleepMs(baseDelayMs * 2 ** (attempt - 1));\n }\n }\n throw last;\n}\n"],"mappings":";AAAA,MAAM,qCAAqC;AAC3C,MAAM,oCAAoC;AAO1C,SAAS,QAAQ,IAA2B;AAC1C,QAAO,IAAI,SAAS,YAAY;AAC9B,aAAW,SAAS,GAAG;GACvB;;AAGJ,SAAS,mCAAmC,OAAyB;AACnE,KAAI,EAAE,iBAAiB,OACrB,QAAO;AAET,KAAI,MAAM,SAAS,aACjB,QAAO;CAET,MAAM,QAAS,MAAsC;AACrD,KAAI,SAAS,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,OAAO;EAC3E,MAAM,OAAQ,MAA6B;AAC3C,MACE,SAAS,gBACN,SAAS,kBACT,SAAS,eACT,SAAS,WACT,SAAS,eACT,SAAS,YAEZ,QAAO;;AAGX,KAAI,iBAAiB,aAAa,MAAM,YAAY,eAClD,QAAO;AAET,QAAO;;AAGT,eAAsB,+BACpB,QACA,UAA0C,EAAE,EAChC;CACZ,MAAM,WAAW,QAAQ,YAAY;CACrC,MAAM,cAAc,QAAQ,eAAe;CAC3C,IAAI;AACJ,MAAK,IAAI,UAAU,GAAG,WAAW,UAAU,UACzC,KAAI;AACF,SAAO,MAAM,QAAQ;UACd,OAAO;AACd,SAAO;AACP,MAAI,YAAY,YAAY,CAAC,mCAAmC,MAAM,CACpE,OAAM;AAER,QAAM,QAAQ,cAAc,MAAM,UAAU,GAAG;;AAGnD,OAAM"}
@@ -0,0 +1,21 @@
1
+ //#region src/utils/marketplace/marketplace-read-source.utils.d.ts
2
+ declare const OFFICIAL_MARKETPLACE_API_BASE = "https://marketplace-api.nextclaw.io";
3
+ declare const DEFAULT_MARKETPLACE_API_BASE = "https://marketplace-api.nextclaw.io";
4
+ type MarketplaceReadResult<T> = {
5
+ apiBase: string;
6
+ data: T;
7
+ };
8
+ declare class MarketplaceRequestError extends Error {
9
+ readonly status?: number | undefined;
10
+ constructor(message: string, status?: number | undefined);
11
+ }
12
+ declare function resolveMarketplaceReadApiBases(explicitBase: string | undefined): readonly string[];
13
+ declare function getMarketplaceReadFetchOptions(apiBase: string): {
14
+ timeoutMs: number;
15
+ retryAttempts: number;
16
+ };
17
+ declare function shouldFallbackMarketplaceReadError(error: unknown): boolean;
18
+ declare function runMarketplaceReadSources<T>(apiBases: readonly string[], action: (apiBase: string) => Promise<T>): Promise<MarketplaceReadResult<T>>;
19
+ //#endregion
20
+ export { DEFAULT_MARKETPLACE_API_BASE, MarketplaceReadResult, MarketplaceRequestError, OFFICIAL_MARKETPLACE_API_BASE, getMarketplaceReadFetchOptions, resolveMarketplaceReadApiBases, runMarketplaceReadSources, shouldFallbackMarketplaceReadError };
21
+ //# sourceMappingURL=marketplace-read-source.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketplace-read-source.utils.d.ts","names":[],"sources":["../../../src/utils/marketplace/marketplace-read-source.utils.ts"],"mappings":";cACa,6BAAA;AAAA,cACA,4BAAA;AAAA,KASD,qBAAA;EACV,OAAA;EACA,IAAA,EAAM,CAAA;AAAA;AAAA,cAGK,uBAAA,SAAgC,KAAA;EAAA,SAGhC,MAAA;cADT,OAAA,UACS,MAAA;AAAA;AAAA,iBAOG,8BAAA,CAA+B,YAAA;AAAA,iBAQ/B,8BAAA,CAA+B,OAAA;EAC7C,SAAA;EACA,aAAA;AAAA;AAAA,iBAcc,kCAAA,CAAmC,KAAA;AAAA,iBAO7B,yBAAA,GAAA,CACpB,QAAA,qBACA,MAAA,GAAS,OAAA,aAAoB,OAAA,CAAQ,CAAA,IACpC,OAAA,CAAQ,qBAAA,CAAsB,CAAA"}
@@ -0,0 +1,51 @@
1
+ //#region src/utils/marketplace/marketplace-read-source.utils.ts
2
+ const DOMESTIC_MARKETPLACE_API_BASE = "https://api.nextclaw.net";
3
+ const OFFICIAL_MARKETPLACE_API_BASE = "https://marketplace-api.nextclaw.io";
4
+ const DEFAULT_MARKETPLACE_API_BASE = OFFICIAL_MARKETPLACE_API_BASE;
5
+ const DEFAULT_MARKETPLACE_READ_API_BASES = [DOMESTIC_MARKETPLACE_API_BASE, OFFICIAL_MARKETPLACE_API_BASE];
6
+ const MARKETPLACE_FETCH_TIMEOUT_MS = 12e3;
7
+ const DOMESTIC_MARKETPLACE_FETCH_TIMEOUT_MS = 2e3;
8
+ const DOMESTIC_MARKETPLACE_RETRY_ATTEMPTS = 2;
9
+ var MarketplaceRequestError = class extends Error {
10
+ constructor(message, status) {
11
+ super(message);
12
+ this.status = status;
13
+ this.name = "MarketplaceRequestError";
14
+ }
15
+ };
16
+ function resolveMarketplaceReadApiBases(explicitBase) {
17
+ const raw = explicitBase?.trim() || process.env.NEXTCLAW_MARKETPLACE_API_BASE?.trim();
18
+ if (raw) return [raw.replace(/\/+$/, "")];
19
+ return DEFAULT_MARKETPLACE_READ_API_BASES;
20
+ }
21
+ function getMarketplaceReadFetchOptions(apiBase) {
22
+ if (apiBase.replace(/\/+$/, "") !== DOMESTIC_MARKETPLACE_API_BASE) return {
23
+ timeoutMs: MARKETPLACE_FETCH_TIMEOUT_MS,
24
+ retryAttempts: 5
25
+ };
26
+ return {
27
+ timeoutMs: DOMESTIC_MARKETPLACE_FETCH_TIMEOUT_MS,
28
+ retryAttempts: DOMESTIC_MARKETPLACE_RETRY_ATTEMPTS
29
+ };
30
+ }
31
+ function shouldFallbackMarketplaceReadError(error) {
32
+ if (!(error instanceof MarketplaceRequestError)) return true;
33
+ return error.status === 408 || error.status === 429 || typeof error.status === "number" && error.status >= 500;
34
+ }
35
+ async function runMarketplaceReadSources(apiBases, action) {
36
+ let lastError;
37
+ for (const apiBase of apiBases) try {
38
+ return {
39
+ apiBase,
40
+ data: await action(apiBase)
41
+ };
42
+ } catch (error) {
43
+ lastError = error;
44
+ if (!shouldFallbackMarketplaceReadError(error)) throw error;
45
+ }
46
+ throw lastError;
47
+ }
48
+ //#endregion
49
+ export { DEFAULT_MARKETPLACE_API_BASE, MarketplaceRequestError, OFFICIAL_MARKETPLACE_API_BASE, getMarketplaceReadFetchOptions, resolveMarketplaceReadApiBases, runMarketplaceReadSources, shouldFallbackMarketplaceReadError };
50
+
51
+ //# sourceMappingURL=marketplace-read-source.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketplace-read-source.utils.js","names":[],"sources":["../../../src/utils/marketplace/marketplace-read-source.utils.ts"],"sourcesContent":["const DOMESTIC_MARKETPLACE_API_BASE = \"https://api.nextclaw.net\";\nexport const OFFICIAL_MARKETPLACE_API_BASE = \"https://marketplace-api.nextclaw.io\";\nexport const DEFAULT_MARKETPLACE_API_BASE = OFFICIAL_MARKETPLACE_API_BASE;\nconst DEFAULT_MARKETPLACE_READ_API_BASES = [\n DOMESTIC_MARKETPLACE_API_BASE,\n OFFICIAL_MARKETPLACE_API_BASE,\n] as const;\nconst MARKETPLACE_FETCH_TIMEOUT_MS = 12_000;\nconst DOMESTIC_MARKETPLACE_FETCH_TIMEOUT_MS = 2_000;\nconst DOMESTIC_MARKETPLACE_RETRY_ATTEMPTS = 2;\n\nexport type MarketplaceReadResult<T> = {\n apiBase: string;\n data: T;\n};\n\nexport class MarketplaceRequestError extends Error {\n constructor(\n message: string,\n readonly status?: number,\n ) {\n super(message);\n this.name = \"MarketplaceRequestError\";\n }\n}\n\nexport function resolveMarketplaceReadApiBases(explicitBase: string | undefined): readonly string[] {\n const raw = explicitBase?.trim() || process.env.NEXTCLAW_MARKETPLACE_API_BASE?.trim();\n if (raw) {\n return [raw.replace(/\\/+$/, \"\")];\n }\n return DEFAULT_MARKETPLACE_READ_API_BASES;\n}\n\nexport function getMarketplaceReadFetchOptions(apiBase: string): {\n timeoutMs: number;\n retryAttempts: number;\n} {\n if (apiBase.replace(/\\/+$/, \"\") !== DOMESTIC_MARKETPLACE_API_BASE) {\n return {\n timeoutMs: MARKETPLACE_FETCH_TIMEOUT_MS,\n retryAttempts: 5,\n };\n }\n return {\n timeoutMs: DOMESTIC_MARKETPLACE_FETCH_TIMEOUT_MS,\n retryAttempts: DOMESTIC_MARKETPLACE_RETRY_ATTEMPTS,\n };\n}\n\nexport function shouldFallbackMarketplaceReadError(error: unknown): boolean {\n if (!(error instanceof MarketplaceRequestError)) {\n return true;\n }\n return error.status === 408 || error.status === 429 || (typeof error.status === \"number\" && error.status >= 500);\n}\n\nexport async function runMarketplaceReadSources<T>(\n apiBases: readonly string[],\n action: (apiBase: string) => Promise<T>,\n): Promise<MarketplaceReadResult<T>> {\n let lastError: unknown;\n for (const apiBase of apiBases) {\n try {\n return {\n apiBase,\n data: await action(apiBase),\n };\n } catch (error) {\n lastError = error;\n if (!shouldFallbackMarketplaceReadError(error)) {\n throw error;\n }\n }\n }\n throw lastError;\n}\n"],"mappings":";AAAA,MAAM,gCAAgC;AACtC,MAAa,gCAAgC;AAC7C,MAAa,+BAA+B;AAC5C,MAAM,qCAAqC,CACzC,+BACA,8BACD;AACD,MAAM,+BAA+B;AACrC,MAAM,wCAAwC;AAC9C,MAAM,sCAAsC;AAO5C,IAAa,0BAAb,cAA6C,MAAM;CACjD,YACE,SACA,QACA;AACA,QAAM,QAAQ;AAFL,OAAA,SAAA;AAGT,OAAK,OAAO;;;AAIhB,SAAgB,+BAA+B,cAAqD;CAClG,MAAM,MAAM,cAAc,MAAM,IAAI,QAAQ,IAAI,+BAA+B,MAAM;AACrF,KAAI,IACF,QAAO,CAAC,IAAI,QAAQ,QAAQ,GAAG,CAAC;AAElC,QAAO;;AAGT,SAAgB,+BAA+B,SAG7C;AACA,KAAI,QAAQ,QAAQ,QAAQ,GAAG,KAAK,8BAClC,QAAO;EACL,WAAW;EACX,eAAe;EAChB;AAEH,QAAO;EACL,WAAW;EACX,eAAe;EAChB;;AAGH,SAAgB,mCAAmC,OAAyB;AAC1E,KAAI,EAAE,iBAAiB,yBACrB,QAAO;AAET,QAAO,MAAM,WAAW,OAAO,MAAM,WAAW,OAAQ,OAAO,MAAM,WAAW,YAAY,MAAM,UAAU;;AAG9G,eAAsB,0BACpB,UACA,QACmC;CACnC,IAAI;AACJ,MAAK,MAAM,WAAW,SACpB,KAAI;AACF,SAAO;GACL;GACA,MAAM,MAAM,OAAO,QAAQ;GAC5B;UACM,OAAO;AACd,cAAY;AACZ,MAAI,CAAC,mCAAmC,MAAM,CAC5C,OAAM;;AAIZ,OAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"marketplace-skill-lifecycle.utils.d.ts","names":[],"sources":["../../../src/utils/marketplace/marketplace-skill-lifecycle.utils.ts"],"mappings":";;;KAsBK,2BAAA;AAAA,KAEO,8BAAA;EACV,IAAA;EACA,OAAA;EACA,GAAA;EACA,KAAA;EACA,UAAA;AAAA;AAAA,iBAGoB,uBAAA,CAAwB,OAAA,EAAS,8BAAA,GAAiC,OAAA;EACtF,IAAA;EACA,cAAA;EACA,gBAAA;EACA,MAAA,EAAQ,2BAAA;AAAA;AAAA,iBAyDY,+BAAA,CAAgC,OAAA,EAAS,8BAAA,GAAiC,OAAA;EAC9F,IAAA;EACA,cAAA;EACA,OAAA;EACA,MAAA,EAAQ,2BAAA;EACR,MAAA,EAAQ,4BAAA;AAAA"}
1
+ {"version":3,"file":"marketplace-skill-lifecycle.utils.d.ts","names":[],"sources":["../../../src/utils/marketplace/marketplace-skill-lifecycle.utils.ts"],"mappings":";;;KAsBK,2BAAA;AAAA,KAEO,8BAAA;EACV,IAAA;EACA,OAAA;EACA,GAAA;EACA,KAAA;EACA,UAAA;AAAA;AAAA,iBAGoB,uBAAA,CAAwB,OAAA,EAAS,8BAAA,GAAiC,OAAA;EACtF,IAAA;EACA,cAAA;EACA,gBAAA;EACA,MAAA,EAAQ,2BAAA;AAAA;AAAA,iBA2DY,+BAAA,CAAgC,OAAA,EAAS,8BAAA,GAAiC,OAAA;EAC9F,IAAA;EACA,cAAA;EACA,OAAA;EACA,MAAA,EAAQ,2BAAA;EACR,MAAA,EAAQ,4BAAA;AAAA"}
@@ -1,5 +1,6 @@
1
1
  import { buildMarketplaceSkillInstallState, hasLocalMarketplaceSkillDrift, isLocalMarketplaceInstallStateFile, readMarketplaceSkillInstallState, resolveMarketplaceSkillUpdateStatus, writeMarketplaceSkillInstallState } from "../../stores/marketplace-install-state.store.js";
2
- import { fetchMarketplaceSkillFiles, fetchMarketplaceSkillItem, resolveMarketplaceApiBase, writeMarketplaceSkillFiles } from "./marketplace-client.utils.js";
2
+ import { resolveMarketplaceReadApiBases } from "./marketplace-read-source.utils.js";
3
+ import { fetchMarketplaceSkillFilesFromSources, fetchMarketplaceSkillItemFromSources, writeMarketplaceSkillFiles } from "./marketplace-client.utils.js";
3
4
  import { validateSkillSelector } from "./marketplace-identity.utils.js";
4
5
  import { DEFAULT_SKILLS_DIR } from "@nextclaw/core";
5
6
  import { SkillManager } from "@nextclaw/kernel";
@@ -11,8 +12,8 @@ async function installMarketplaceSkill(options) {
11
12
  const selector = validateSkillSelector(slug.trim(), "slug");
12
13
  const workdir = resolve(rawWorkdir);
13
14
  if (!existsSync(workdir)) throw new Error(`Workdir does not exist: ${workdir}`);
14
- const apiBase = resolveMarketplaceApiBase(apiBaseUrl);
15
- const item = await fetchMarketplaceSkillItem(apiBase, selector);
15
+ const apiBases = resolveMarketplaceReadApiBases(apiBaseUrl);
16
+ const item = (await fetchMarketplaceSkillItemFromSources(apiBases, selector)).data;
16
17
  const installSlug = item.slug;
17
18
  const resolvedSlug = item.packageName || item.slug;
18
19
  const destinationDir = resolveMarketplaceSkillDestinationDir({
@@ -28,7 +29,8 @@ async function installMarketplaceSkill(options) {
28
29
  builtinResult.slug = resolvedSlug;
29
30
  return builtinResult;
30
31
  }
31
- const filesPayload = await fetchMarketplaceSkillFiles(apiBase, selector);
32
+ const filesResult = await fetchMarketplaceSkillFilesFromSources(apiBases, selector);
33
+ const filesPayload = filesResult.data;
32
34
  const existingInstall = prepareMarketplaceSkillDestinationDir({
33
35
  destinationDir,
34
36
  files: filesPayload.files,
@@ -42,7 +44,7 @@ async function installMarketplaceSkill(options) {
42
44
  const writtenFiles = await writeMarketplaceSkillFiles({
43
45
  destinationDir,
44
46
  files: filesPayload.files,
45
- apiBase,
47
+ apiBase: filesResult.apiBase,
46
48
  slug: selector
47
49
  });
48
50
  ensureInstalledMarketplaceSkill(destinationDir, installSlug);
@@ -50,7 +52,7 @@ async function installMarketplaceSkill(options) {
50
52
  destinationDir,
51
53
  state: buildMarketplaceSkillInstallState({
52
54
  item,
53
- apiBase,
55
+ apiBase: filesResult.apiBase,
54
56
  files: writtenFiles
55
57
  })
56
58
  });
@@ -61,8 +63,8 @@ async function updateInstalledMarketplaceSkill(options) {
61
63
  const selector = validateSkillSelector(slug.trim(), "slug");
62
64
  const workdir = resolve(rawWorkdir);
63
65
  if (!existsSync(workdir)) throw new Error(`Workdir does not exist: ${workdir}`);
64
- const apiBase = resolveMarketplaceApiBase(apiBaseUrl);
65
- const item = await fetchMarketplaceSkillItem(apiBase, selector);
66
+ const apiBases = resolveMarketplaceReadApiBases(apiBaseUrl);
67
+ const item = (await fetchMarketplaceSkillItemFromSources(apiBases, selector)).data;
66
68
  const destinationDir = resolveMarketplaceSkillDestinationDir({
67
69
  workdir,
68
70
  slug: item.slug,
@@ -87,7 +89,8 @@ async function updateInstalledMarketplaceSkill(options) {
87
89
  source: "marketplace",
88
90
  status
89
91
  };
90
- const filesPayload = await fetchMarketplaceSkillFiles(apiBase, selector);
92
+ const filesResult = await fetchMarketplaceSkillFilesFromSources(apiBases, selector);
93
+ const filesPayload = filesResult.data;
91
94
  rmSync(destinationDir, {
92
95
  recursive: true,
93
96
  force: true
@@ -96,7 +99,7 @@ async function updateInstalledMarketplaceSkill(options) {
96
99
  const writtenFiles = await writeMarketplaceSkillFiles({
97
100
  destinationDir,
98
101
  files: filesPayload.files,
99
- apiBase,
102
+ apiBase: filesResult.apiBase,
100
103
  slug: selector
101
104
  });
102
105
  ensureInstalledMarketplaceSkill(destinationDir, item.slug);
@@ -104,7 +107,7 @@ async function updateInstalledMarketplaceSkill(options) {
104
107
  destinationDir,
105
108
  state: buildMarketplaceSkillInstallState({
106
109
  item,
107
- apiBase,
110
+ apiBase: filesResult.apiBase,
108
111
  files: writtenFiles
109
112
  })
110
113
  });
@@ -1 +1 @@
1
- {"version":3,"file":"marketplace-skill-lifecycle.utils.js","names":[],"sources":["../../../src/utils/marketplace/marketplace-skill-lifecycle.utils.ts"],"sourcesContent":["import { existsSync, mkdirSync, readdirSync, rmSync } from \"node:fs\";\nimport { isAbsolute, join, relative, resolve } from \"node:path\";\nimport { DEFAULT_SKILLS_DIR } from \"@nextclaw/core\";\nimport { SkillManager } from \"@nextclaw/kernel\";\nimport {\n fetchMarketplaceSkillFiles,\n fetchMarketplaceSkillItem,\n resolveMarketplaceApiBase,\n type MarketplaceSkillFileManifestEntry,\n writeMarketplaceSkillFiles\n} from \"@nextclaw-service/utils/marketplace/marketplace-client.utils.js\";\nimport {\n buildMarketplaceSkillInstallState,\n hasLocalMarketplaceSkillDrift,\n isLocalMarketplaceInstallStateFile,\n readMarketplaceSkillInstallState,\n resolveMarketplaceSkillUpdateStatus,\n type MarketplaceSkillUpdateStatus,\n writeMarketplaceSkillInstallState\n} from \"@nextclaw-service/stores/marketplace-install-state.store.js\";\nimport { validateSkillSelector } from \"@nextclaw-service/utils/marketplace/marketplace-identity.utils.js\";\n\ntype MarketplaceSkillInstallKind = \"builtin\" | \"marketplace\";\n\nexport type MarketplaceSkillInstallOptions = {\n slug: string;\n workdir: string;\n dir?: string;\n force?: boolean;\n apiBaseUrl?: string;\n};\n\nexport async function installMarketplaceSkill(options: MarketplaceSkillInstallOptions): Promise<{\n slug: string;\n destinationDir: string;\n alreadyInstalled?: boolean;\n source: MarketplaceSkillInstallKind;\n}> {\n const { slug, workdir: rawWorkdir, dir, force, apiBaseUrl } = options;\n const selector = validateSkillSelector(slug.trim(), \"slug\");\n const workdir = resolve(rawWorkdir);\n if (!existsSync(workdir)) {\n throw new Error(`Workdir does not exist: ${workdir}`);\n }\n\n const apiBase = resolveMarketplaceApiBase(apiBaseUrl);\n const item = await fetchMarketplaceSkillItem(apiBase, selector);\n const installSlug = item.slug;\n const resolvedSlug = item.packageName || item.slug;\n const destinationDir = resolveMarketplaceSkillDestinationDir({\n workdir,\n slug: installSlug,\n dir,\n });\n\n if (item.install.kind === \"builtin\") {\n const builtinResult = resolveBuiltinMarketplaceInstallResult({\n workdir,\n slug: installSlug,\n });\n builtinResult.slug = resolvedSlug;\n return builtinResult;\n }\n\n const filesPayload = await fetchMarketplaceSkillFiles(apiBase, selector);\n const existingInstall = prepareMarketplaceSkillDestinationDir({\n destinationDir,\n files: filesPayload.files,\n force,\n slug: installSlug,\n });\n if (existingInstall) {\n existingInstall.slug = resolvedSlug;\n return existingInstall;\n }\n const writtenFiles = await writeMarketplaceSkillFiles({\n destinationDir,\n files: filesPayload.files,\n apiBase,\n slug: selector,\n });\n ensureInstalledMarketplaceSkill(destinationDir, installSlug);\n writeMarketplaceSkillInstallState({\n destinationDir,\n state: buildMarketplaceSkillInstallState({\n item,\n apiBase,\n files: writtenFiles,\n }),\n });\n return buildMarketplaceInstallResult(resolvedSlug, destinationDir);\n}\n\nexport async function updateInstalledMarketplaceSkill(options: MarketplaceSkillInstallOptions): Promise<{\n slug: string;\n destinationDir: string;\n updated: boolean;\n source: MarketplaceSkillInstallKind;\n status: MarketplaceSkillUpdateStatus;\n}> {\n const { slug, workdir: rawWorkdir, dir, force, apiBaseUrl } = options;\n const selector = validateSkillSelector(slug.trim(), \"slug\");\n const workdir = resolve(rawWorkdir);\n if (!existsSync(workdir)) {\n throw new Error(`Workdir does not exist: ${workdir}`);\n }\n\n const apiBase = resolveMarketplaceApiBase(apiBaseUrl);\n const item = await fetchMarketplaceSkillItem(apiBase, selector);\n const destinationDir = resolveMarketplaceSkillDestinationDir({\n workdir,\n slug: item.slug,\n dir,\n });\n\n if (item.install.kind === \"builtin\") {\n return {\n slug: item.packageName || item.slug,\n destinationDir: resolveBuiltinSkillDir(workdir, item.slug),\n updated: false,\n source: \"builtin\",\n status: \"up-to-date\",\n };\n }\n\n if (!existsSync(destinationDir)) {\n throw new Error(`Marketplace skill is not installed: ${item.slug}`);\n }\n\n const currentState = readMarketplaceSkillInstallState(destinationDir);\n if (!currentState && !force) {\n throw new Error(`Missing marketplace install state for ${item.slug}; use --force to replace this skill from marketplace.`);\n }\n\n if (!force && currentState && hasLocalMarketplaceSkillDrift(destinationDir, currentState)) {\n throw new Error(`Local skill files changed since install: ${item.slug}; use --force to overwrite local changes.`);\n }\n\n const status = resolveMarketplaceSkillUpdateStatus(currentState, item.updatedAt);\n if (!force && status === \"up-to-date\") {\n return {\n slug: item.packageName || item.slug,\n destinationDir,\n updated: false,\n source: \"marketplace\",\n status,\n };\n }\n\n const filesPayload = await fetchMarketplaceSkillFiles(apiBase, selector);\n rmSync(destinationDir, { recursive: true, force: true });\n mkdirSync(destinationDir, { recursive: true });\n const writtenFiles = await writeMarketplaceSkillFiles({\n destinationDir,\n files: filesPayload.files,\n apiBase,\n slug: selector,\n });\n ensureInstalledMarketplaceSkill(destinationDir, item.slug);\n writeMarketplaceSkillInstallState({\n destinationDir,\n state: buildMarketplaceSkillInstallState({\n item,\n apiBase,\n files: writtenFiles,\n }),\n });\n\n return {\n slug: item.packageName || item.slug,\n destinationDir,\n updated: true,\n source: \"marketplace\",\n status: \"up-to-date\",\n };\n}\n\nfunction resolveMarketplaceSkillDestinationDir(params: {\n workdir: string;\n slug: string;\n dir?: string;\n}): string {\n const { workdir, slug, dir } = params;\n const dirName = dir?.trim() || DEFAULT_SKILLS_DIR;\n return isAbsolute(dirName)\n ? resolve(dirName, slug)\n : resolve(workdir, dirName, slug);\n}\n\nfunction resolveBuiltinMarketplaceInstallResult(params: {\n workdir: string;\n slug: string;\n}): {\n slug: string;\n destinationDir: string;\n alreadyInstalled: true;\n source: \"builtin\";\n} {\n return {\n slug: params.slug,\n destinationDir: resolveBuiltinSkillDir(params.workdir, params.slug),\n alreadyInstalled: true,\n source: \"builtin\",\n };\n}\n\nfunction prepareMarketplaceSkillDestinationDir(params: {\n destinationDir: string;\n files: MarketplaceSkillFileManifestEntry[];\n force?: boolean;\n slug: string;\n}): {\n slug: string;\n destinationDir: string;\n alreadyInstalled: true;\n source: \"marketplace\";\n} | null {\n const { destinationDir, files, force, slug } = params;\n if (!force && existsSync(destinationDir)) {\n const existingDirState = inspectMarketplaceSkillDirectory(destinationDir, files);\n if (existingDirState === \"installed\") {\n return {\n slug,\n destinationDir,\n alreadyInstalled: true,\n source: \"marketplace\",\n };\n }\n if (existingDirState !== \"recoverable\") {\n throw new Error(`Skill directory already exists: ${destinationDir} (use --force)`);\n }\n rmSync(destinationDir, { recursive: true, force: true });\n }\n\n if (force && existsSync(destinationDir)) {\n rmSync(destinationDir, { recursive: true, force: true });\n }\n\n mkdirSync(destinationDir, { recursive: true });\n return null;\n}\n\nfunction ensureInstalledMarketplaceSkill(destinationDir: string, slug: string): void {\n if (!existsSync(join(destinationDir, \"SKILL.md\"))) {\n throw new Error(`Marketplace skill ${slug} does not include SKILL.md`);\n }\n}\n\nfunction buildMarketplaceInstallResult(slug: string, destinationDir: string): {\n slug: string;\n destinationDir: string;\n source: \"marketplace\";\n} {\n return {\n slug,\n destinationDir,\n source: \"marketplace\",\n };\n}\n\nfunction inspectMarketplaceSkillDirectory(\n destinationDir: string,\n files: MarketplaceSkillFileManifestEntry[]\n): \"installed\" | \"recoverable\" | \"conflict\" {\n if (existsSync(join(destinationDir, \"SKILL.md\"))) {\n return \"installed\";\n }\n\n const discoveredFiles = collectRelativeFiles(destinationDir);\n if (discoveredFiles === null) {\n return \"conflict\";\n }\n\n const relevantFiles = discoveredFiles.filter((file) => !isIgnorableMarketplaceResidue(file));\n if (relevantFiles.length === 0) {\n return \"recoverable\";\n }\n\n const manifestPaths = new Set(files.map((file) => normalizeMarketplaceRelativePath(file.path)));\n return relevantFiles.every((file) => manifestPaths.has(normalizeMarketplaceRelativePath(file)))\n ? \"recoverable\"\n : \"conflict\";\n}\n\nfunction collectRelativeFiles(rootDir: string): string[] | null {\n const output: string[] = [];\n const walk = (dir: string): boolean => {\n const entries = readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const absolute = join(dir, entry.name);\n if (entry.isDirectory()) {\n if (!walk(absolute)) {\n return false;\n }\n continue;\n }\n if (!entry.isFile()) {\n return false;\n }\n const relativePath = relative(rootDir, absolute);\n output.push(normalizeMarketplaceRelativePath(relativePath));\n }\n return true;\n };\n\n return walk(rootDir) ? output : null;\n}\n\nfunction normalizeMarketplaceRelativePath(path: string): string {\n return path.replace(/\\\\/g, \"/\");\n}\n\nfunction isIgnorableMarketplaceResidue(path: string): boolean {\n return path === \".DS_Store\" || isLocalMarketplaceInstallStateFile(path);\n}\n\nfunction resolveBuiltinSkillDir(workdir: string, skillName: string): string {\n const skillDir = new SkillManager({ workspace: workdir }).resolveBuiltinSkillDir(skillName);\n if (!skillDir) {\n throw new Error(`Built-in skill not found in local installation: ${skillName}`);\n }\n return skillDir;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"marketplace-skill-lifecycle.utils.js","names":[],"sources":["../../../src/utils/marketplace/marketplace-skill-lifecycle.utils.ts"],"sourcesContent":["import { existsSync, mkdirSync, readdirSync, rmSync } from \"node:fs\";\nimport { isAbsolute, join, relative, resolve } from \"node:path\";\nimport { DEFAULT_SKILLS_DIR } from \"@nextclaw/core\";\nimport { SkillManager } from \"@nextclaw/kernel\";\nimport {\n fetchMarketplaceSkillFilesFromSources,\n fetchMarketplaceSkillItemFromSources,\n resolveMarketplaceReadApiBases,\n type MarketplaceSkillFileManifestEntry,\n writeMarketplaceSkillFiles\n} from \"@nextclaw-service/utils/marketplace/marketplace-client.utils.js\";\nimport {\n buildMarketplaceSkillInstallState,\n hasLocalMarketplaceSkillDrift,\n isLocalMarketplaceInstallStateFile,\n readMarketplaceSkillInstallState,\n resolveMarketplaceSkillUpdateStatus,\n type MarketplaceSkillUpdateStatus,\n writeMarketplaceSkillInstallState\n} from \"@nextclaw-service/stores/marketplace-install-state.store.js\";\nimport { validateSkillSelector } from \"@nextclaw-service/utils/marketplace/marketplace-identity.utils.js\";\n\ntype MarketplaceSkillInstallKind = \"builtin\" | \"marketplace\";\n\nexport type MarketplaceSkillInstallOptions = {\n slug: string;\n workdir: string;\n dir?: string;\n force?: boolean;\n apiBaseUrl?: string;\n};\n\nexport async function installMarketplaceSkill(options: MarketplaceSkillInstallOptions): Promise<{\n slug: string;\n destinationDir: string;\n alreadyInstalled?: boolean;\n source: MarketplaceSkillInstallKind;\n}> {\n const { slug, workdir: rawWorkdir, dir, force, apiBaseUrl } = options;\n const selector = validateSkillSelector(slug.trim(), \"slug\");\n const workdir = resolve(rawWorkdir);\n if (!existsSync(workdir)) {\n throw new Error(`Workdir does not exist: ${workdir}`);\n }\n\n const apiBases = resolveMarketplaceReadApiBases(apiBaseUrl);\n const itemResult = await fetchMarketplaceSkillItemFromSources(apiBases, selector);\n const item = itemResult.data;\n const installSlug = item.slug;\n const resolvedSlug = item.packageName || item.slug;\n const destinationDir = resolveMarketplaceSkillDestinationDir({\n workdir,\n slug: installSlug,\n dir,\n });\n\n if (item.install.kind === \"builtin\") {\n const builtinResult = resolveBuiltinMarketplaceInstallResult({\n workdir,\n slug: installSlug,\n });\n builtinResult.slug = resolvedSlug;\n return builtinResult;\n }\n\n const filesResult = await fetchMarketplaceSkillFilesFromSources(apiBases, selector);\n const filesPayload = filesResult.data;\n const existingInstall = prepareMarketplaceSkillDestinationDir({\n destinationDir,\n files: filesPayload.files,\n force,\n slug: installSlug,\n });\n if (existingInstall) {\n existingInstall.slug = resolvedSlug;\n return existingInstall;\n }\n const writtenFiles = await writeMarketplaceSkillFiles({\n destinationDir,\n files: filesPayload.files,\n apiBase: filesResult.apiBase,\n slug: selector,\n });\n ensureInstalledMarketplaceSkill(destinationDir, installSlug);\n writeMarketplaceSkillInstallState({\n destinationDir,\n state: buildMarketplaceSkillInstallState({\n item,\n apiBase: filesResult.apiBase,\n files: writtenFiles,\n }),\n });\n return buildMarketplaceInstallResult(resolvedSlug, destinationDir);\n}\n\nexport async function updateInstalledMarketplaceSkill(options: MarketplaceSkillInstallOptions): Promise<{\n slug: string;\n destinationDir: string;\n updated: boolean;\n source: MarketplaceSkillInstallKind;\n status: MarketplaceSkillUpdateStatus;\n}> {\n const { slug, workdir: rawWorkdir, dir, force, apiBaseUrl } = options;\n const selector = validateSkillSelector(slug.trim(), \"slug\");\n const workdir = resolve(rawWorkdir);\n if (!existsSync(workdir)) {\n throw new Error(`Workdir does not exist: ${workdir}`);\n }\n\n const apiBases = resolveMarketplaceReadApiBases(apiBaseUrl);\n const itemResult = await fetchMarketplaceSkillItemFromSources(apiBases, selector);\n const item = itemResult.data;\n const destinationDir = resolveMarketplaceSkillDestinationDir({\n workdir,\n slug: item.slug,\n dir,\n });\n\n if (item.install.kind === \"builtin\") {\n return {\n slug: item.packageName || item.slug,\n destinationDir: resolveBuiltinSkillDir(workdir, item.slug),\n updated: false,\n source: \"builtin\",\n status: \"up-to-date\",\n };\n }\n\n if (!existsSync(destinationDir)) {\n throw new Error(`Marketplace skill is not installed: ${item.slug}`);\n }\n\n const currentState = readMarketplaceSkillInstallState(destinationDir);\n if (!currentState && !force) {\n throw new Error(`Missing marketplace install state for ${item.slug}; use --force to replace this skill from marketplace.`);\n }\n\n if (!force && currentState && hasLocalMarketplaceSkillDrift(destinationDir, currentState)) {\n throw new Error(`Local skill files changed since install: ${item.slug}; use --force to overwrite local changes.`);\n }\n\n const status = resolveMarketplaceSkillUpdateStatus(currentState, item.updatedAt);\n if (!force && status === \"up-to-date\") {\n return {\n slug: item.packageName || item.slug,\n destinationDir,\n updated: false,\n source: \"marketplace\",\n status,\n };\n }\n\n const filesResult = await fetchMarketplaceSkillFilesFromSources(apiBases, selector);\n const filesPayload = filesResult.data;\n rmSync(destinationDir, { recursive: true, force: true });\n mkdirSync(destinationDir, { recursive: true });\n const writtenFiles = await writeMarketplaceSkillFiles({\n destinationDir,\n files: filesPayload.files,\n apiBase: filesResult.apiBase,\n slug: selector,\n });\n ensureInstalledMarketplaceSkill(destinationDir, item.slug);\n writeMarketplaceSkillInstallState({\n destinationDir,\n state: buildMarketplaceSkillInstallState({\n item,\n apiBase: filesResult.apiBase,\n files: writtenFiles,\n }),\n });\n\n return {\n slug: item.packageName || item.slug,\n destinationDir,\n updated: true,\n source: \"marketplace\",\n status: \"up-to-date\",\n };\n}\n\nfunction resolveMarketplaceSkillDestinationDir(params: {\n workdir: string;\n slug: string;\n dir?: string;\n}): string {\n const { workdir, slug, dir } = params;\n const dirName = dir?.trim() || DEFAULT_SKILLS_DIR;\n return isAbsolute(dirName)\n ? resolve(dirName, slug)\n : resolve(workdir, dirName, slug);\n}\n\nfunction resolveBuiltinMarketplaceInstallResult(params: {\n workdir: string;\n slug: string;\n}): {\n slug: string;\n destinationDir: string;\n alreadyInstalled: true;\n source: \"builtin\";\n} {\n return {\n slug: params.slug,\n destinationDir: resolveBuiltinSkillDir(params.workdir, params.slug),\n alreadyInstalled: true,\n source: \"builtin\",\n };\n}\n\nfunction prepareMarketplaceSkillDestinationDir(params: {\n destinationDir: string;\n files: MarketplaceSkillFileManifestEntry[];\n force?: boolean;\n slug: string;\n}): {\n slug: string;\n destinationDir: string;\n alreadyInstalled: true;\n source: \"marketplace\";\n} | null {\n const { destinationDir, files, force, slug } = params;\n if (!force && existsSync(destinationDir)) {\n const existingDirState = inspectMarketplaceSkillDirectory(destinationDir, files);\n if (existingDirState === \"installed\") {\n return {\n slug,\n destinationDir,\n alreadyInstalled: true,\n source: \"marketplace\",\n };\n }\n if (existingDirState !== \"recoverable\") {\n throw new Error(`Skill directory already exists: ${destinationDir} (use --force)`);\n }\n rmSync(destinationDir, { recursive: true, force: true });\n }\n\n if (force && existsSync(destinationDir)) {\n rmSync(destinationDir, { recursive: true, force: true });\n }\n\n mkdirSync(destinationDir, { recursive: true });\n return null;\n}\n\nfunction ensureInstalledMarketplaceSkill(destinationDir: string, slug: string): void {\n if (!existsSync(join(destinationDir, \"SKILL.md\"))) {\n throw new Error(`Marketplace skill ${slug} does not include SKILL.md`);\n }\n}\n\nfunction buildMarketplaceInstallResult(slug: string, destinationDir: string): {\n slug: string;\n destinationDir: string;\n source: \"marketplace\";\n} {\n return {\n slug,\n destinationDir,\n source: \"marketplace\",\n };\n}\n\nfunction inspectMarketplaceSkillDirectory(\n destinationDir: string,\n files: MarketplaceSkillFileManifestEntry[]\n): \"installed\" | \"recoverable\" | \"conflict\" {\n if (existsSync(join(destinationDir, \"SKILL.md\"))) {\n return \"installed\";\n }\n\n const discoveredFiles = collectRelativeFiles(destinationDir);\n if (discoveredFiles === null) {\n return \"conflict\";\n }\n\n const relevantFiles = discoveredFiles.filter((file) => !isIgnorableMarketplaceResidue(file));\n if (relevantFiles.length === 0) {\n return \"recoverable\";\n }\n\n const manifestPaths = new Set(files.map((file) => normalizeMarketplaceRelativePath(file.path)));\n return relevantFiles.every((file) => manifestPaths.has(normalizeMarketplaceRelativePath(file)))\n ? \"recoverable\"\n : \"conflict\";\n}\n\nfunction collectRelativeFiles(rootDir: string): string[] | null {\n const output: string[] = [];\n const walk = (dir: string): boolean => {\n const entries = readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const absolute = join(dir, entry.name);\n if (entry.isDirectory()) {\n if (!walk(absolute)) {\n return false;\n }\n continue;\n }\n if (!entry.isFile()) {\n return false;\n }\n const relativePath = relative(rootDir, absolute);\n output.push(normalizeMarketplaceRelativePath(relativePath));\n }\n return true;\n };\n\n return walk(rootDir) ? output : null;\n}\n\nfunction normalizeMarketplaceRelativePath(path: string): string {\n return path.replace(/\\\\/g, \"/\");\n}\n\nfunction isIgnorableMarketplaceResidue(path: string): boolean {\n return path === \".DS_Store\" || isLocalMarketplaceInstallStateFile(path);\n}\n\nfunction resolveBuiltinSkillDir(workdir: string, skillName: string): string {\n const skillDir = new SkillManager({ workspace: workdir }).resolveBuiltinSkillDir(skillName);\n if (!skillDir) {\n throw new Error(`Built-in skill not found in local installation: ${skillName}`);\n }\n return skillDir;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/service",
3
- "version": "0.2.17",
3
+ "version": "0.2.18",
4
4
  "private": false,
5
5
  "description": "NextClaw long-running service host and runtime lifecycle.",
6
6
  "type": "module",
@@ -42,31 +42,31 @@
42
42
  "chokidar": "^3.6.0",
43
43
  "commander": "^12.1.0",
44
44
  "jszip": "^3.10.1",
45
- "@nextclaw/channel-extension-dingtalk": "0.1.21",
46
- "@nextclaw/channel-extension-email": "0.1.21",
47
- "@nextclaw/channel-extension-qq": "0.1.24",
48
- "@nextclaw/channel-extension-slack": "0.1.21",
49
- "@nextclaw/channel-extension-feishu": "0.1.27",
50
- "@nextclaw/channel-extension-wecom": "0.1.21",
51
- "@nextclaw/channel-extension-discord": "0.1.21",
52
- "@nextclaw/channel-extension-weixin": "0.1.31",
53
- "@nextclaw/client-sdk": "0.4.6",
54
- "@nextclaw/core": "0.14.7",
55
- "@nextclaw/kernel": "0.5.3",
56
- "@nextclaw/mcp": "0.2.17",
57
- "@nextclaw/ncp": "0.6.5",
58
- "@nextclaw/channel-extension-telegram": "0.1.21",
59
- "@nextclaw/ncp-mcp": "0.1.112",
60
- "@nextclaw/ncp-toolkit": "0.5.40",
61
- "@nextclaw/nextclaw-hermes-acp-bridge": "0.2.15",
62
- "@nextclaw/nextclaw-ncp-runtime-http-client": "0.2.15",
63
- "@nextclaw/nextclaw-ncp-runtime-stdio-client": "0.2.16",
64
- "@nextclaw/remote": "0.2.17",
65
- "@nextclaw/runtime": "0.3.17",
66
- "@nextclaw/server": "0.14.7",
67
- "@nextclaw/shared": "0.3.2",
68
- "@nextclaw/channel-extension-whatsapp": "0.1.21",
69
- "@nextclaw/ncp-agent-runtime": "0.3.46"
45
+ "@nextclaw/channel-extension-dingtalk": "0.1.22",
46
+ "@nextclaw/channel-extension-discord": "0.1.22",
47
+ "@nextclaw/channel-extension-slack": "0.1.22",
48
+ "@nextclaw/channel-extension-email": "0.1.22",
49
+ "@nextclaw/channel-extension-feishu": "0.1.28",
50
+ "@nextclaw/channel-extension-qq": "0.1.25",
51
+ "@nextclaw/channel-extension-weixin": "0.1.32",
52
+ "@nextclaw/channel-extension-telegram": "0.1.22",
53
+ "@nextclaw/channel-extension-wecom": "0.1.22",
54
+ "@nextclaw/channel-extension-whatsapp": "0.1.22",
55
+ "@nextclaw/core": "0.14.8",
56
+ "@nextclaw/client-sdk": "0.4.7",
57
+ "@nextclaw/kernel": "0.5.4",
58
+ "@nextclaw/ncp": "0.6.6",
59
+ "@nextclaw/mcp": "0.2.18",
60
+ "@nextclaw/ncp-agent-runtime": "0.3.47",
61
+ "@nextclaw/ncp-mcp": "0.1.113",
62
+ "@nextclaw/ncp-toolkit": "0.5.41",
63
+ "@nextclaw/nextclaw-hermes-acp-bridge": "0.2.16",
64
+ "@nextclaw/nextclaw-ncp-runtime-http-client": "0.2.16",
65
+ "@nextclaw/nextclaw-ncp-runtime-stdio-client": "0.2.17",
66
+ "@nextclaw/runtime": "0.3.18",
67
+ "@nextclaw/shared": "0.3.3",
68
+ "@nextclaw/server": "0.14.8",
69
+ "@nextclaw/remote": "0.2.18"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/node": "^20.17.6",