@clawstore/clawstore 1.0.0 → 1.0.2
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/clawstore-clawstore-1.0.2.tgz +0 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/src/__tests__/cli-sim.test.d.ts +9 -0
- package/dist/src/__tests__/cli-sim.test.d.ts.map +1 -0
- package/dist/src/__tests__/cli-sim.test.js +275 -0
- package/dist/src/__tests__/cli-sim.test.js.map +1 -0
- package/dist/src/__tests__/e2e.test.d.ts +10 -0
- package/dist/src/__tests__/e2e.test.d.ts.map +1 -0
- package/dist/src/__tests__/e2e.test.js +159 -0
- package/dist/src/__tests__/e2e.test.js.map +1 -0
- package/dist/src/cli.d.ts +3 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +470 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/commands.d.ts +10 -0
- package/dist/src/commands.d.ts.map +1 -0
- package/dist/src/commands.js +208 -0
- package/dist/src/commands.js.map +1 -0
- package/dist/src/constants.d.ts +28 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +65 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/core/agent-manager.d.ts +34 -0
- package/dist/src/core/agent-manager.d.ts.map +1 -0
- package/dist/src/core/agent-manager.js +268 -0
- package/dist/src/core/agent-manager.js.map +1 -0
- package/dist/src/core/package-installer.d.ts +30 -0
- package/dist/src/core/package-installer.d.ts.map +1 -0
- package/dist/src/core/package-installer.js +308 -0
- package/dist/src/core/package-installer.js.map +1 -0
- package/dist/src/core/packager.d.ts +20 -0
- package/dist/src/core/packager.d.ts.map +1 -0
- package/dist/src/core/packager.js +178 -0
- package/dist/src/core/packager.js.map +1 -0
- package/dist/src/core/skill-installer.d.ts +33 -0
- package/dist/src/core/skill-installer.d.ts.map +1 -0
- package/dist/src/core/skill-installer.js +179 -0
- package/dist/src/core/skill-installer.js.map +1 -0
- package/dist/src/core/store-client.d.ts +47 -0
- package/dist/src/core/store-client.d.ts.map +1 -0
- package/dist/src/core/store-client.js +111 -0
- package/dist/src/core/store-client.js.map +1 -0
- package/dist/src/core/workspace.d.ts +29 -0
- package/dist/src/core/workspace.d.ts.map +1 -0
- package/dist/src/core/workspace.js +242 -0
- package/dist/src/core/workspace.js.map +1 -0
- package/dist/src/types.d.ts +114 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +3 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils/checksum.d.ts +4 -0
- package/dist/src/utils/checksum.d.ts.map +1 -0
- package/dist/src/utils/checksum.js +15 -0
- package/dist/src/utils/checksum.js.map +1 -0
- package/dist/src/utils/output.d.ts +13 -0
- package/dist/src/utils/output.d.ts.map +1 -0
- package/dist/src/utils/output.js +70 -0
- package/dist/src/utils/output.js.map +1 -0
- package/dist/src/utils/zip.d.ts +13 -0
- package/dist/src/utils/zip.d.ts.map +1 -0
- package/dist/src/utils/zip.js +50 -0
- package/dist/src/utils/zip.js.map +1 -0
- package/package.json +4 -2
- package/src/cli.ts +29 -11
- package/src/commands.ts +33 -3
- package/src/constants.ts +1 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export interface SkillDependency {
|
|
2
|
+
id: string;
|
|
3
|
+
version: string;
|
|
4
|
+
required: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface AgentManifest {
|
|
7
|
+
id: string;
|
|
8
|
+
slug: string;
|
|
9
|
+
name: string;
|
|
10
|
+
subtitle: string;
|
|
11
|
+
description: string;
|
|
12
|
+
version: string;
|
|
13
|
+
author: string;
|
|
14
|
+
author_id?: string;
|
|
15
|
+
homepage?: string;
|
|
16
|
+
license: string;
|
|
17
|
+
price: number;
|
|
18
|
+
currency: string;
|
|
19
|
+
category: string;
|
|
20
|
+
tags: string[];
|
|
21
|
+
icon?: string;
|
|
22
|
+
screenshots?: string[];
|
|
23
|
+
openclaw_version: string;
|
|
24
|
+
entry_files: string[];
|
|
25
|
+
skills: SkillDependency[];
|
|
26
|
+
checksum?: string;
|
|
27
|
+
published_at?: string;
|
|
28
|
+
updated_at?: string;
|
|
29
|
+
source_agent_id?: string;
|
|
30
|
+
packed_at?: string;
|
|
31
|
+
packaged_by?: string;
|
|
32
|
+
detection_mode?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface InstalledAgentRecord {
|
|
35
|
+
id: string;
|
|
36
|
+
name: string;
|
|
37
|
+
version: string;
|
|
38
|
+
category: string;
|
|
39
|
+
author: string;
|
|
40
|
+
enabled: boolean;
|
|
41
|
+
installed_at: string;
|
|
42
|
+
updated_at: string;
|
|
43
|
+
source: string;
|
|
44
|
+
install_path: string;
|
|
45
|
+
backup_path: string;
|
|
46
|
+
disable_backup_path?: string;
|
|
47
|
+
files: string[];
|
|
48
|
+
skills: string[];
|
|
49
|
+
}
|
|
50
|
+
export interface AgentRegistry {
|
|
51
|
+
agents: Record<string, InstalledAgentRecord>;
|
|
52
|
+
}
|
|
53
|
+
export interface InstalledSkillRecord {
|
|
54
|
+
skill_id: string;
|
|
55
|
+
version: string;
|
|
56
|
+
installed_at: string;
|
|
57
|
+
installed_by: string;
|
|
58
|
+
source: string;
|
|
59
|
+
}
|
|
60
|
+
export interface SkillRegistry {
|
|
61
|
+
skills: Record<string, InstalledSkillRecord>;
|
|
62
|
+
}
|
|
63
|
+
export type InstallState = "idle" | "fetching_manifest" | "downloading_package" | "verifying_package" | "checking_compatibility" | "installing_skills" | "installing_agent" | "registering_agent" | "rolling_back" | "success" | "failed";
|
|
64
|
+
export type PackState = "idle" | "loading_agent" | "collecting_files" | "detecting_skills" | "awaiting_confirmation" | "generating_agent_json" | "packing_zip" | "saving_or_uploading" | "success" | "failed";
|
|
65
|
+
export interface ClawstoreConfig {
|
|
66
|
+
apiBaseUrl: string;
|
|
67
|
+
autoCheckUpdates: boolean;
|
|
68
|
+
autoInstallSkills: boolean;
|
|
69
|
+
}
|
|
70
|
+
export interface StoreAgentSummary {
|
|
71
|
+
id: string;
|
|
72
|
+
name: string;
|
|
73
|
+
subtitle: string;
|
|
74
|
+
author: string;
|
|
75
|
+
price: number;
|
|
76
|
+
currency: string;
|
|
77
|
+
category: string;
|
|
78
|
+
rating: number;
|
|
79
|
+
downloads: number;
|
|
80
|
+
openclaw_version: string;
|
|
81
|
+
}
|
|
82
|
+
export interface StoreAgentDetail extends StoreAgentSummary {
|
|
83
|
+
description: string;
|
|
84
|
+
tags: string[];
|
|
85
|
+
skills: SkillDependency[];
|
|
86
|
+
version: string;
|
|
87
|
+
screenshots: string[];
|
|
88
|
+
published_at: string;
|
|
89
|
+
updated_at: string;
|
|
90
|
+
}
|
|
91
|
+
export interface StoreSearchResult {
|
|
92
|
+
total: number;
|
|
93
|
+
agents: StoreAgentSummary[];
|
|
94
|
+
}
|
|
95
|
+
export interface DiagnosticCheck {
|
|
96
|
+
label: string;
|
|
97
|
+
path?: string;
|
|
98
|
+
status: "ok" | "warn" | "fail";
|
|
99
|
+
detail?: string;
|
|
100
|
+
}
|
|
101
|
+
export interface DiagnosticReport {
|
|
102
|
+
checks: DiagnosticCheck[];
|
|
103
|
+
allOk: boolean;
|
|
104
|
+
}
|
|
105
|
+
export interface ValidationError {
|
|
106
|
+
field: string;
|
|
107
|
+
message: string;
|
|
108
|
+
}
|
|
109
|
+
export interface PackageValidationResult {
|
|
110
|
+
valid: boolean;
|
|
111
|
+
errors: ValidationError[];
|
|
112
|
+
manifest: AgentManifest | null;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,uEAAuE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checksum.d.ts","sourceRoot":"","sources":["../../../src/utils/checksum.ts"],"names":[],"mappings":"AAGA,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIrE;AAED,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGzE;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
export async function computeSha256(filePath) {
|
|
4
|
+
const data = await readFile(filePath);
|
|
5
|
+
const hash = createHash("sha256").update(data).digest("hex");
|
|
6
|
+
return `sha256:${hash.substring(0, 16)}`;
|
|
7
|
+
}
|
|
8
|
+
export async function computeFullSha256(filePath) {
|
|
9
|
+
const data = await readFile(filePath);
|
|
10
|
+
return createHash("sha256").update(data).digest("hex");
|
|
11
|
+
}
|
|
12
|
+
export function hashBuffer(buf) {
|
|
13
|
+
return createHash("sha256").update(buf).digest("hex");
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=checksum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checksum.js","sourceRoot":"","sources":["../../../src/utils/checksum.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB;IAClD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7D,OAAO,UAAU,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,QAAgB;IACtD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACtC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatting helpers for CLI/slash command output.
|
|
3
|
+
* Follows the Clawstore output design spec: result first, details second,
|
|
4
|
+
* short text for next-step guidance.
|
|
5
|
+
*/
|
|
6
|
+
export declare function stepLine(step: number, total: number, label: string, status: string): string;
|
|
7
|
+
export declare function successBanner(agentName: string, version: string, extra?: Record<string, string>): string;
|
|
8
|
+
export declare function errorBanner(action: string, agentId: string, step: string, reason: string): string;
|
|
9
|
+
export declare function agentListItem(index: number, id: string, name: string, version: string, category: string, enabled: boolean): string;
|
|
10
|
+
export declare function detailBlock(fields: Record<string, string | undefined>): string;
|
|
11
|
+
export declare function searchResultItem(index: number, id: string, name: string, price: number, currency: string, author: string, rating: number): string;
|
|
12
|
+
export declare function indentLines(text: string, indent?: number): string;
|
|
13
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/utils/output.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3F;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAexG;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAWjG;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAOlI;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,CAS9E;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAOjJ;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,MAAM,CAMpE"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatting helpers for CLI/slash command output.
|
|
3
|
+
* Follows the Clawstore output design spec: result first, details second,
|
|
4
|
+
* short text for next-step guidance.
|
|
5
|
+
*/
|
|
6
|
+
export function stepLine(step, total, label, status) {
|
|
7
|
+
return ` [${step}/${total}] ${label} ... ${status}`;
|
|
8
|
+
}
|
|
9
|
+
export function successBanner(agentName, version, extra) {
|
|
10
|
+
const lines = [
|
|
11
|
+
"",
|
|
12
|
+
` Installed: ${agentName}@${version}`,
|
|
13
|
+
];
|
|
14
|
+
if (extra) {
|
|
15
|
+
for (const [k, v] of Object.entries(extra)) {
|
|
16
|
+
lines.push(` ${k}: ${v}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
lines.push(" Status: enabled");
|
|
20
|
+
lines.push("");
|
|
21
|
+
lines.push(" Next: start a new chat in OpenClaw to activate the new persona");
|
|
22
|
+
lines.push("");
|
|
23
|
+
return lines.join("\n");
|
|
24
|
+
}
|
|
25
|
+
export function errorBanner(action, agentId, step, reason) {
|
|
26
|
+
return [
|
|
27
|
+
"",
|
|
28
|
+
` ${action} failed: ${agentId}`,
|
|
29
|
+
` Step: ${step}`,
|
|
30
|
+
` Reason: ${reason}`,
|
|
31
|
+
" Next:",
|
|
32
|
+
" 1. Run `openclaw clawstore doctor`",
|
|
33
|
+
` 2. Retry \`openclaw clawstore ${action.toLowerCase()} ${agentId}\``,
|
|
34
|
+
"",
|
|
35
|
+
].join("\n");
|
|
36
|
+
}
|
|
37
|
+
export function agentListItem(index, id, name, version, category, enabled) {
|
|
38
|
+
const status = enabled ? "enabled" : "disabled";
|
|
39
|
+
return [
|
|
40
|
+
` ${index}. ${id}`,
|
|
41
|
+
` ${name}`,
|
|
42
|
+
` v${version} · ${category} · ${status}`,
|
|
43
|
+
].join("\n");
|
|
44
|
+
}
|
|
45
|
+
export function detailBlock(fields) {
|
|
46
|
+
const lines = [""];
|
|
47
|
+
for (const [k, v] of Object.entries(fields)) {
|
|
48
|
+
if (v !== undefined) {
|
|
49
|
+
lines.push(` ${k}: ${v}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
lines.push("");
|
|
53
|
+
return lines.join("\n");
|
|
54
|
+
}
|
|
55
|
+
export function searchResultItem(index, id, name, price, currency, author, rating) {
|
|
56
|
+
const priceStr = price === 0 ? "Free" : `${currency === "USD" ? "$" : currency}${price}`;
|
|
57
|
+
return [
|
|
58
|
+
` ${index}. ${id}`,
|
|
59
|
+
` ${name}`,
|
|
60
|
+
` ${priceStr} · by ${author} · rating ${rating.toFixed(1)}`,
|
|
61
|
+
].join("\n");
|
|
62
|
+
}
|
|
63
|
+
export function indentLines(text, indent = 2) {
|
|
64
|
+
const pad = " ".repeat(indent);
|
|
65
|
+
return text
|
|
66
|
+
.split("\n")
|
|
67
|
+
.map((l) => (l.trim() ? `${pad}${l}` : l))
|
|
68
|
+
.join("\n");
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/utils/output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract a ZIP to a cache directory, returning the effective package root.
|
|
3
|
+
* If the ZIP contains a single top-level directory, that directory is returned.
|
|
4
|
+
*/
|
|
5
|
+
export declare function extractZip(zipPath: string): Promise<string>;
|
|
6
|
+
/**
|
|
7
|
+
* Create a ZIP from a source directory, excluding hidden files and __pycache__.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createZip(sourceDir: string, outputPath: string): Promise<{
|
|
10
|
+
path: string;
|
|
11
|
+
sizeBytes: number;
|
|
12
|
+
}>;
|
|
13
|
+
//# sourceMappingURL=zip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zip.d.ts","sourceRoot":"","sources":["../../../src/utils/zip.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBjE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAwBnH"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import AdmZip from "adm-zip";
|
|
2
|
+
import { mkdir, readdir, stat } from "node:fs/promises";
|
|
3
|
+
import { join, relative } from "node:path";
|
|
4
|
+
import { CACHE_DIR } from "../constants.js";
|
|
5
|
+
/**
|
|
6
|
+
* Extract a ZIP to a cache directory, returning the effective package root.
|
|
7
|
+
* If the ZIP contains a single top-level directory, that directory is returned.
|
|
8
|
+
*/
|
|
9
|
+
export async function extractZip(zipPath) {
|
|
10
|
+
const zip = new AdmZip(zipPath);
|
|
11
|
+
const baseName = zipPath.replace(/\.zip$/i, "").split(/[\\/]/).pop();
|
|
12
|
+
const extractDir = join(CACHE_DIR, baseName);
|
|
13
|
+
await mkdir(extractDir, { recursive: true });
|
|
14
|
+
zip.extractAllTo(extractDir, true);
|
|
15
|
+
const children = await readdir(extractDir);
|
|
16
|
+
if (children.length === 1) {
|
|
17
|
+
const child = join(extractDir, children[0]);
|
|
18
|
+
const st = await stat(child);
|
|
19
|
+
if (st.isDirectory())
|
|
20
|
+
return child;
|
|
21
|
+
}
|
|
22
|
+
return extractDir;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Create a ZIP from a source directory, excluding hidden files and __pycache__.
|
|
26
|
+
*/
|
|
27
|
+
export async function createZip(sourceDir, outputPath) {
|
|
28
|
+
const zip = new AdmZip();
|
|
29
|
+
async function walk(dir) {
|
|
30
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
if (entry.name.startsWith(".") || entry.name === "__pycache__" || entry.name === "node_modules") {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const fullPath = join(dir, entry.name);
|
|
36
|
+
const arcPath = relative(sourceDir, fullPath);
|
|
37
|
+
if (entry.isDirectory()) {
|
|
38
|
+
await walk(fullPath);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
zip.addLocalFile(fullPath, relative(sourceDir, dir) || undefined);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
await walk(sourceDir);
|
|
46
|
+
zip.writeZip(outputPath);
|
|
47
|
+
const st = await stat(outputPath);
|
|
48
|
+
return { path: outputPath, sizeBytes: st.size };
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=zip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zip.js","sourceRoot":"","sources":["../../../src/utils/zip.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAe;IAC9C,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAG,CAAC;IACtE,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAE7C,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,GAAG,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAEnC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,EAAE,CAAC,WAAW,EAAE;YAAE,OAAO,KAAK,CAAC;IACrC,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,SAAiB,EAAE,UAAkB;IACnE,MAAM,GAAG,GAAG,IAAI,MAAM,EAAE,CAAC;IAEzB,KAAK,UAAU,IAAI,CAAC,GAAW;QAC7B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;gBAChG,SAAS;YACX,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAC9C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC;IACtB,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAEzB,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC;IAClC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;AAClD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clawstore/clawstore",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Agent marketplace plugin for OpenClaw — browse, install, manage and pack AI employee agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.ts",
|
|
7
7
|
"openclaw": {
|
|
8
|
-
"extensions": [
|
|
8
|
+
"extensions": [
|
|
9
|
+
"./index.ts"
|
|
10
|
+
],
|
|
9
11
|
"install": {
|
|
10
12
|
"npmSpec": "@clawstore/clawstore",
|
|
11
13
|
"localPath": "extensions/clawstore"
|
package/src/cli.ts
CHANGED
|
@@ -19,7 +19,7 @@ import { installAgent, updateAgent } from "./core/package-installer.js";
|
|
|
19
19
|
import { packAgent, packCurrentAgent } from "./core/packager.js";
|
|
20
20
|
import { diagnose, formatDiagnosticReport, listClawstoreAgents } from "./core/workspace.js";
|
|
21
21
|
import { StoreClient } from "./core/store-client.js";
|
|
22
|
-
import { DEFAULT_API_BASE_URL, DEFAULT_AGENT } from "./constants.js";
|
|
22
|
+
import { DEFAULT_API_BASE_URL, DEFAULT_AGENT, STORE_DOWNLOAD_BASE_URL } from "./constants.js";
|
|
23
23
|
import {
|
|
24
24
|
agentListItem,
|
|
25
25
|
detailBlock,
|
|
@@ -134,28 +134,46 @@ export function registerClawstoreCli(api: OpenClawPluginApi): void {
|
|
|
134
134
|
// ── install ─────────────────────────────────────────────────
|
|
135
135
|
root
|
|
136
136
|
.command("install <source>")
|
|
137
|
-
.description("Install an Agent from local path, ZIP, or marketplace")
|
|
137
|
+
.description("Install an Agent from local path, ZIP, URL, or marketplace")
|
|
138
138
|
.option("-f, --force", "Force reinstall if already installed")
|
|
139
139
|
.option(A_FLAGS, A_DESC, DEFAULT_AGENT)
|
|
140
140
|
.action(async (source: string, opts: { force?: boolean; agent?: string }) => {
|
|
141
141
|
const agent = opts.agent ?? DEFAULT_AGENT;
|
|
142
142
|
let packagePath = source;
|
|
143
143
|
|
|
144
|
+
const isUrl = /^https?:\/\//i.test(source);
|
|
145
|
+
|
|
144
146
|
const isRemote =
|
|
147
|
+
!isUrl &&
|
|
145
148
|
!source.includes("/") &&
|
|
146
149
|
!source.includes("\\") &&
|
|
147
150
|
!source.endsWith(".zip") &&
|
|
148
151
|
!existsSync(source);
|
|
149
152
|
|
|
150
|
-
if (
|
|
153
|
+
if (isUrl) {
|
|
154
|
+
const slug = source.split("/").pop()?.replace(/\.zip$/i, "") ?? "remote-agent";
|
|
155
|
+
try {
|
|
156
|
+
console.log(`\n Downloading from URL ...`);
|
|
157
|
+
console.log(` ${source}`);
|
|
158
|
+
const { downloadPackage } = await import("./core/package-installer.js");
|
|
159
|
+
packagePath = await downloadPackage(source, slug);
|
|
160
|
+
console.log(` Downloaded to: ${packagePath}\n`);
|
|
161
|
+
} catch (err) {
|
|
162
|
+
console.log(`\n Failed to download from URL: ${(err as Error).message}`);
|
|
163
|
+
console.log(` URL: ${source}`);
|
|
164
|
+
console.log(` Try downloading manually and installing from local path.\n`);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
} else if (isRemote) {
|
|
168
|
+
const downloadUrl = `${STORE_DOWNLOAD_BASE_URL}/${source}`;
|
|
151
169
|
try {
|
|
152
|
-
console.log(`\n
|
|
153
|
-
const url = await client.getDownloadUrl(source);
|
|
170
|
+
console.log(`\n Downloading ${source} from clawstore.pro ...`);
|
|
154
171
|
const { downloadPackage } = await import("./core/package-installer.js");
|
|
155
|
-
packagePath = await downloadPackage(
|
|
172
|
+
packagePath = await downloadPackage(downloadUrl, source);
|
|
156
173
|
console.log(` Downloaded to: ${packagePath}\n`);
|
|
157
174
|
} catch (err) {
|
|
158
|
-
console.log(`\n Failed to download '${source}' from
|
|
175
|
+
console.log(`\n Failed to download '${source}' from clawstore.pro: ${(err as Error).message}`);
|
|
176
|
+
console.log(` URL: ${downloadUrl}`);
|
|
159
177
|
console.log(` If this is a local path, make sure the file/directory exists.\n`);
|
|
160
178
|
return;
|
|
161
179
|
}
|
|
@@ -282,7 +300,7 @@ export function registerClawstoreCli(api: OpenClawPluginApi): void {
|
|
|
282
300
|
console.log(`\n Checking updates for ${personas.length} agent(s)...\n`);
|
|
283
301
|
for (const a of personas) {
|
|
284
302
|
try {
|
|
285
|
-
const downloadUrl =
|
|
303
|
+
const downloadUrl = `${STORE_DOWNLOAD_BASE_URL}/${a.id}`;
|
|
286
304
|
const { downloadPackage } = await import("./core/package-installer.js");
|
|
287
305
|
const pkgPath = await downloadPackage(downloadUrl, a.id);
|
|
288
306
|
await updateAgent({ agentId: a.id, packagePath: pkgPath, agent, log: console.log });
|
|
@@ -301,12 +319,12 @@ export function registerClawstoreCli(api: OpenClawPluginApi): void {
|
|
|
301
319
|
const packagePath = opts.package;
|
|
302
320
|
if (!packagePath) {
|
|
303
321
|
try {
|
|
304
|
-
const
|
|
322
|
+
const downloadUrl = `${STORE_DOWNLOAD_BASE_URL}/${agentId}`;
|
|
305
323
|
const { downloadPackage } = await import("./core/package-installer.js");
|
|
306
|
-
const dlPath = await downloadPackage(
|
|
324
|
+
const dlPath = await downloadPackage(downloadUrl, agentId);
|
|
307
325
|
await updateAgent({ agentId, packagePath: dlPath, agent, log: console.log });
|
|
308
326
|
} catch (err) {
|
|
309
|
-
console.log(`\n Could not fetch update from
|
|
327
|
+
console.log(`\n Could not fetch update from clawstore.pro: ${(err as Error).message}`);
|
|
310
328
|
console.log(` Provide a local package: openclaw clawstore update ${agentId} --package <path>\n`);
|
|
311
329
|
}
|
|
312
330
|
return;
|
package/src/commands.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
|
2
2
|
import type { ClawstoreConfig } from "./types.js";
|
|
3
3
|
import { StoreClient } from "./core/store-client.js";
|
|
4
|
-
import { DEFAULT_AGENT } from "./constants.js";
|
|
4
|
+
import { DEFAULT_AGENT, STORE_DOWNLOAD_BASE_URL } from "./constants.js";
|
|
5
5
|
import {
|
|
6
6
|
listInstalledAgents,
|
|
7
7
|
getInstalledAgent,
|
|
@@ -70,10 +70,40 @@ export function registerClawstoreCommand(api: OpenClawPluginApi): void {
|
|
|
70
70
|
// ── /clawstore install <source> ─────────────────────────
|
|
71
71
|
case "install": {
|
|
72
72
|
const source = rest[0];
|
|
73
|
-
if (!source) return { text: "Usage: /clawstore install <agent-id|path>" };
|
|
73
|
+
if (!source) return { text: "Usage: /clawstore install <agent-id|path|url>" };
|
|
74
74
|
const lines: string[] = [];
|
|
75
|
+
let packagePath = source;
|
|
76
|
+
|
|
77
|
+
const isUrl = /^https?:\/\//i.test(source);
|
|
78
|
+
|
|
79
|
+
const { existsSync } = await import("node:fs");
|
|
80
|
+
const isRemote =
|
|
81
|
+
!isUrl &&
|
|
82
|
+
!source.includes("/") &&
|
|
83
|
+
!source.includes("\\") &&
|
|
84
|
+
!source.endsWith(".zip") &&
|
|
85
|
+
!existsSync(source);
|
|
86
|
+
|
|
87
|
+
if (isUrl) {
|
|
88
|
+
try {
|
|
89
|
+
const slug = source.split("/").pop()?.replace(/\.zip$/i, "") ?? "remote-agent";
|
|
90
|
+
const { downloadPackage } = await import("./core/package-installer.js");
|
|
91
|
+
packagePath = await downloadPackage(source, slug);
|
|
92
|
+
} catch (err) {
|
|
93
|
+
return { text: `URL download failed: ${(err as Error).message}\n\nTry downloading manually:\n\`Invoke-WebRequest -Uri "${source}" -OutFile agent.zip\`\n\`openclaw clawstore install ./agent.zip\`` };
|
|
94
|
+
}
|
|
95
|
+
} else if (isRemote) {
|
|
96
|
+
try {
|
|
97
|
+
const downloadUrl = `${STORE_DOWNLOAD_BASE_URL}/${source}`;
|
|
98
|
+
const { downloadPackage } = await import("./core/package-installer.js");
|
|
99
|
+
packagePath = await downloadPackage(downloadUrl, source);
|
|
100
|
+
} catch (err) {
|
|
101
|
+
return { text: `Download failed: ${(err as Error).message}\n\nUse CLI: \`openclaw clawstore install ${source}\`` };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
75
105
|
const result = await installAgent({
|
|
76
|
-
packagePath
|
|
106
|
+
packagePath,
|
|
77
107
|
agent,
|
|
78
108
|
log: (msg) => lines.push(msg),
|
|
79
109
|
});
|
package/src/constants.ts
CHANGED
|
@@ -71,6 +71,7 @@ export const MANIFEST_REQUIRED_FIELDS = [
|
|
|
71
71
|
// ─── Default API ────────────────────────────────────────────────────
|
|
72
72
|
|
|
73
73
|
export const DEFAULT_API_BASE_URL = "https://api.shopclawmart.com";
|
|
74
|
+
export const STORE_DOWNLOAD_BASE_URL = "https://clawstore.pro/api/agent/download";
|
|
74
75
|
|
|
75
76
|
// ─── Install Steps ──────────────────────────────────────────────────
|
|
76
77
|
|