@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.
Files changed (69) hide show
  1. package/clawstore-clawstore-1.0.2.tgz +0 -0
  2. package/dist/index.d.ts +24 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +40 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/src/__tests__/cli-sim.test.d.ts +9 -0
  7. package/dist/src/__tests__/cli-sim.test.d.ts.map +1 -0
  8. package/dist/src/__tests__/cli-sim.test.js +275 -0
  9. package/dist/src/__tests__/cli-sim.test.js.map +1 -0
  10. package/dist/src/__tests__/e2e.test.d.ts +10 -0
  11. package/dist/src/__tests__/e2e.test.d.ts.map +1 -0
  12. package/dist/src/__tests__/e2e.test.js +159 -0
  13. package/dist/src/__tests__/e2e.test.js.map +1 -0
  14. package/dist/src/cli.d.ts +3 -0
  15. package/dist/src/cli.d.ts.map +1 -0
  16. package/dist/src/cli.js +470 -0
  17. package/dist/src/cli.js.map +1 -0
  18. package/dist/src/commands.d.ts +10 -0
  19. package/dist/src/commands.d.ts.map +1 -0
  20. package/dist/src/commands.js +208 -0
  21. package/dist/src/commands.js.map +1 -0
  22. package/dist/src/constants.d.ts +28 -0
  23. package/dist/src/constants.d.ts.map +1 -0
  24. package/dist/src/constants.js +65 -0
  25. package/dist/src/constants.js.map +1 -0
  26. package/dist/src/core/agent-manager.d.ts +34 -0
  27. package/dist/src/core/agent-manager.d.ts.map +1 -0
  28. package/dist/src/core/agent-manager.js +268 -0
  29. package/dist/src/core/agent-manager.js.map +1 -0
  30. package/dist/src/core/package-installer.d.ts +30 -0
  31. package/dist/src/core/package-installer.d.ts.map +1 -0
  32. package/dist/src/core/package-installer.js +308 -0
  33. package/dist/src/core/package-installer.js.map +1 -0
  34. package/dist/src/core/packager.d.ts +20 -0
  35. package/dist/src/core/packager.d.ts.map +1 -0
  36. package/dist/src/core/packager.js +178 -0
  37. package/dist/src/core/packager.js.map +1 -0
  38. package/dist/src/core/skill-installer.d.ts +33 -0
  39. package/dist/src/core/skill-installer.d.ts.map +1 -0
  40. package/dist/src/core/skill-installer.js +179 -0
  41. package/dist/src/core/skill-installer.js.map +1 -0
  42. package/dist/src/core/store-client.d.ts +47 -0
  43. package/dist/src/core/store-client.d.ts.map +1 -0
  44. package/dist/src/core/store-client.js +111 -0
  45. package/dist/src/core/store-client.js.map +1 -0
  46. package/dist/src/core/workspace.d.ts +29 -0
  47. package/dist/src/core/workspace.d.ts.map +1 -0
  48. package/dist/src/core/workspace.js +242 -0
  49. package/dist/src/core/workspace.js.map +1 -0
  50. package/dist/src/types.d.ts +114 -0
  51. package/dist/src/types.d.ts.map +1 -0
  52. package/dist/src/types.js +3 -0
  53. package/dist/src/types.js.map +1 -0
  54. package/dist/src/utils/checksum.d.ts +4 -0
  55. package/dist/src/utils/checksum.d.ts.map +1 -0
  56. package/dist/src/utils/checksum.js +15 -0
  57. package/dist/src/utils/checksum.js.map +1 -0
  58. package/dist/src/utils/output.d.ts +13 -0
  59. package/dist/src/utils/output.d.ts.map +1 -0
  60. package/dist/src/utils/output.js +70 -0
  61. package/dist/src/utils/output.js.map +1 -0
  62. package/dist/src/utils/zip.d.ts +13 -0
  63. package/dist/src/utils/zip.d.ts.map +1 -0
  64. package/dist/src/utils/zip.js +50 -0
  65. package/dist/src/utils/zip.js.map +1 -0
  66. package/package.json +4 -2
  67. package/src/cli.ts +29 -11
  68. package/src/commands.ts +33 -3
  69. 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,3 @@
1
+ // ─── Agent Manifest (agent.json) ────────────────────────────────────
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,uEAAuE"}
@@ -0,0 +1,4 @@
1
+ export declare function computeSha256(filePath: string): Promise<string>;
2
+ export declare function computeFullSha256(filePath: string): Promise<string>;
3
+ export declare function hashBuffer(buf: Buffer): string;
4
+ //# sourceMappingURL=checksum.d.ts.map
@@ -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.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": ["./index.ts"],
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 (isRemote) {
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 Fetching ${source} from Clawstore...`);
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(url, source);
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 Clawstore: ${(err as Error).message}`);
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 = await client.getDownloadUrl(a.id);
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 url = await client.getDownloadUrl(agentId);
322
+ const downloadUrl = `${STORE_DOWNLOAD_BASE_URL}/${agentId}`;
305
323
  const { downloadPackage } = await import("./core/package-installer.js");
306
- const dlPath = await downloadPackage(url, agentId);
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 Clawstore: ${(err as Error).message}`);
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: source,
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