@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.
- package/dist/services/cron/cron-local.service.d.ts +2 -1
- package/dist/services/cron/cron-local.service.d.ts.map +1 -1
- package/dist/services/marketplace/skills-query.service.d.ts +4 -2
- package/dist/services/marketplace/skills-query.service.d.ts.map +1 -1
- package/dist/services/marketplace/skills-query.service.js +45 -26
- package/dist/services/marketplace/skills-query.service.js.map +1 -1
- package/dist/services/runtime/runtime-config-init.service.d.ts +1 -1
- package/dist/utils/marketplace/marketplace-client.utils.d.ts +6 -1
- package/dist/utils/marketplace/marketplace-client.utils.d.ts.map +1 -1
- package/dist/utils/marketplace/marketplace-client.utils.js +36 -21
- package/dist/utils/marketplace/marketplace-client.utils.js.map +1 -1
- package/dist/utils/marketplace/marketplace-network-retry.utils.d.ts +5 -1
- package/dist/utils/marketplace/marketplace-network-retry.utils.d.ts.map +1 -1
- package/dist/utils/marketplace/marketplace-network-retry.utils.js +6 -4
- package/dist/utils/marketplace/marketplace-network-retry.utils.js.map +1 -1
- package/dist/utils/marketplace/marketplace-read-source.utils.d.ts +21 -0
- package/dist/utils/marketplace/marketplace-read-source.utils.d.ts.map +1 -0
- package/dist/utils/marketplace/marketplace-read-source.utils.js +51 -0
- package/dist/utils/marketplace/marketplace-read-source.utils.js.map +1 -0
- package/dist/utils/marketplace/marketplace-skill-lifecycle.utils.d.ts.map +1 -1
- package/dist/utils/marketplace/marketplace-skill-lifecycle.utils.js +14 -11
- package/dist/utils/marketplace/marketplace-skill-lifecycle.utils.js.map +1 -1
- 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?:
|
|
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":"
|
|
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
|
-
}) =>
|
|
76
|
+
}) => _$_nextclaw_kernel0.InstalledSkillsList;
|
|
76
77
|
getInstalledInfo: (params: {
|
|
77
78
|
workdir: string;
|
|
78
79
|
selector: string;
|
|
79
|
-
}) =>
|
|
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":"
|
|
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 {
|
|
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
|
-
|
|
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
|
|
40
|
+
const apiBaseUrls = resolveMarketplaceReadApiBases(params.apiBaseUrl);
|
|
41
41
|
const encodedSlug = encodeURIComponent(slug);
|
|
42
|
-
const
|
|
43
|
-
|
|
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
|
-
|
|
50
|
-
|
|
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(
|
|
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
|
-
|
|
119
|
-
for (const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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?:
|
|
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":"
|
|
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() ||
|
|
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)}`, {
|
|
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`, {
|
|
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, {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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":"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"}
|
|
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
|
-
|
|
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":";
|
|
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 <=
|
|
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 ===
|
|
27
|
-
await sleepMs(
|
|
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
|
|
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,
|
|
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 {
|
|
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
|
|
15
|
-
const item = await
|
|
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
|
|
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
|
|
65
|
-
const item = await
|
|
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
|
|
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.
|
|
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.
|
|
46
|
-
"@nextclaw/channel-extension-
|
|
47
|
-
"@nextclaw/channel-extension-
|
|
48
|
-
"@nextclaw/channel-extension-
|
|
49
|
-
"@nextclaw/channel-extension-feishu": "0.1.
|
|
50
|
-
"@nextclaw/channel-extension-
|
|
51
|
-
"@nextclaw/channel-extension-
|
|
52
|
-
"@nextclaw/channel-extension-
|
|
53
|
-
"@nextclaw/
|
|
54
|
-
"@nextclaw/
|
|
55
|
-
"@nextclaw/
|
|
56
|
-
"@nextclaw/
|
|
57
|
-
"@nextclaw/
|
|
58
|
-
"@nextclaw/
|
|
59
|
-
"@nextclaw/
|
|
60
|
-
"@nextclaw/ncp-
|
|
61
|
-
"@nextclaw/
|
|
62
|
-
"@nextclaw/
|
|
63
|
-
"@nextclaw/nextclaw-
|
|
64
|
-
"@nextclaw/
|
|
65
|
-
"@nextclaw/runtime": "0.
|
|
66
|
-
"@nextclaw/
|
|
67
|
-
"@nextclaw/shared": "0.3.
|
|
68
|
-
"@nextclaw/
|
|
69
|
-
"@nextclaw/
|
|
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",
|