@zshuangmu/agenthub 0.4.14 → 0.4.16

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 (43) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +268 -268
  3. package/package.json +41 -41
  4. package/src/api-server.js +518 -244
  5. package/src/cli.js +714 -671
  6. package/src/commands/api.js +9 -9
  7. package/src/commands/doctor.js +335 -335
  8. package/src/commands/info.js +15 -15
  9. package/src/commands/install.js +56 -56
  10. package/src/commands/list.js +78 -78
  11. package/src/commands/pack.js +249 -156
  12. package/src/commands/publish-remote.js +9 -9
  13. package/src/commands/publish.js +7 -7
  14. package/src/commands/rollback.js +59 -59
  15. package/src/commands/search.js +14 -14
  16. package/src/commands/serve.js +9 -9
  17. package/src/commands/stats.js +105 -105
  18. package/src/commands/uninstall.js +76 -76
  19. package/src/commands/update.js +54 -54
  20. package/src/commands/verify.js +133 -133
  21. package/src/commands/versions.js +75 -75
  22. package/src/commands/web.js +9 -9
  23. package/src/index.js +18 -18
  24. package/src/lib/auth.js +301 -0
  25. package/src/lib/bundle-transfer.js +58 -58
  26. package/src/lib/colors.js +60 -60
  27. package/src/lib/database.js +450 -244
  28. package/src/lib/debug.js +135 -135
  29. package/src/lib/fs-utils.js +107 -50
  30. package/src/lib/html.js +2163 -1824
  31. package/src/lib/http.js +168 -168
  32. package/src/lib/install.js +60 -60
  33. package/src/lib/manifest.js +124 -124
  34. package/src/lib/openclaw-config.js +40 -40
  35. package/src/lib/permissions.js +105 -0
  36. package/src/lib/privacy-engine.js +220 -0
  37. package/src/lib/registry.js +130 -130
  38. package/src/lib/remote.js +11 -11
  39. package/src/lib/security-scanner.js +233 -233
  40. package/src/lib/signing.js +158 -0
  41. package/src/lib/version-manager.js +77 -77
  42. package/src/server.js +176 -176
  43. package/src/web-server.js +135 -135
@@ -1,105 +1,105 @@
1
- /**
2
- * Stats Command
3
- * 查看 Agent 统计信息
4
- */
5
-
6
- import path from "node:path";
7
- import { pathExists, readJson } from "../lib/fs-utils.js";
8
- import { fetchRemoteJson } from "../lib/remote.js";
9
- import { parseSpec, getLatestVersion } from "../lib/registry.js";
10
-
11
- /**
12
- * 构建统计返回对象的辅助函数
13
- */
14
- function buildStatsResult(slug, manifest, agentEntries) {
15
- const latestEntry = getLatestVersion(agentEntries);
16
- return {
17
- slug,
18
- name: manifest.name,
19
- latestVersion: latestEntry.version,
20
- totalVersions: agentEntries.length,
21
- description: manifest.description,
22
- author: manifest.author,
23
- runtime: manifest.runtime,
24
- includes: manifest.includes,
25
- requirements: manifest.requirements,
26
- metadata: manifest.metadata,
27
- downloads: manifest.downloads || 0,
28
- stars: manifest.stats?.stars || 0,
29
- rating: manifest.stats?.rating || null,
30
- };
31
- }
32
-
33
- export async function statsCommand(agentSpec, options = {}) {
34
- const { slug } = parseSpec(agentSpec);
35
-
36
- if (!options.registry) {
37
- const [manifest, agentsResult] = await Promise.all([
38
- fetchRemoteJson(`/api/agents/${slug}`, options),
39
- fetchRemoteJson(`/api/agents?q=${encodeURIComponent(slug)}`, options),
40
- ]);
41
-
42
- const agentEntries = (agentsResult.agents || []).filter((entry) => entry.slug === slug);
43
- if (agentEntries.length === 0) {
44
- throw new Error(`Agent not found: ${slug}`);
45
- }
46
-
47
- return buildStatsResult(slug, manifest, agentEntries);
48
- }
49
-
50
- const registryDir = path.resolve(options.registry);
51
- const indexPath = path.join(registryDir, "index.json");
52
- if (!(await pathExists(indexPath))) {
53
- throw new Error(`Agent not found: ${slug}`);
54
- }
55
-
56
- const index = await readJson(indexPath);
57
- const agentEntries = index.agents.filter((entry) => entry.slug === slug);
58
-
59
- if (agentEntries.length === 0) {
60
- throw new Error(`Agent not found: ${slug}`);
61
- }
62
-
63
- const latestEntry = getLatestVersion(agentEntries);
64
- const manifestPath = path.join(
65
- registryDir,
66
- "agents",
67
- slug,
68
- latestEntry.version,
69
- "MANIFEST.json"
70
- );
71
- const manifest = await readJson(manifestPath);
72
-
73
- return buildStatsResult(slug, manifest, agentEntries);
74
- }
75
-
76
- export function formatStatsOutput(stats) {
77
- const lines = [];
78
- lines.push("\n╔═══════════════════════════════════════════════════════════════╗");
79
- lines.push("║ Agent Statistics ║");
80
- lines.push("╠═══════════════════════════════════════════════════════════════╣");
81
- lines.push(`║ Name: ${stats.name.substring(0, 44).padEnd(44)}║`);
82
- lines.push(`║ Slug: ${stats.slug.padEnd(44)}║`);
83
- lines.push(`║ Version: ${stats.latestVersion.padEnd(44)}║`);
84
- lines.push(`║ Author: ${(stats.author || "unknown").padEnd(44)}║`);
85
- lines.push("╠═══════════════════════════════════════════════════════════════╣");
86
- lines.push("║ Statistics: ║");
87
- lines.push(`║ Downloads: ${String(stats.downloads).padEnd(44)}║`);
88
- lines.push(`║ Stars: ${String(stats.stars).padEnd(44)}║`);
89
- lines.push(`║ Versions: ${String(stats.totalVersions).padEnd(44)}║`);
90
- if (stats.rating) {
91
- lines.push(`║ Rating: ${`${stats.rating}/5.0`.padEnd(44)}║`);
92
- }
93
- lines.push("╠═══════════════════════════════════════════════════════════════╣");
94
- lines.push("║ Content: ║");
95
- const memory = stats.includes?.memory || {};
96
- lines.push(`║ Memory: ${`共 ${memory.count || 0} 条 (public: ${memory.public || 0}, portable: ${memory.portable || 0})`.padEnd(42)}║`);
97
- if (stats.includes?.skills?.length > 0) {
98
- lines.push(`║ Skills: ${stats.includes.skills.join(", ").substring(0, 42).padEnd(42)}║`);
99
- }
100
- lines.push("╠═══════════════════════════════════════════════════════════════╣");
101
- lines.push(`║ Runtime: ${`${stats.runtime?.type || "openclaw"} ${stats.runtime?.version || ""}`.padEnd(44)}║`);
102
- lines.push("╚═══════════════════════════════════════════════════════════════╝");
103
-
104
- return lines.join("\n");
105
- }
1
+ /**
2
+ * Stats Command
3
+ * 查看 Agent 统计信息
4
+ */
5
+
6
+ import path from "node:path";
7
+ import { pathExists, readJson } from "../lib/fs-utils.js";
8
+ import { fetchRemoteJson } from "../lib/remote.js";
9
+ import { parseSpec, getLatestVersion } from "../lib/registry.js";
10
+
11
+ /**
12
+ * 构建统计返回对象的辅助函数
13
+ */
14
+ function buildStatsResult(slug, manifest, agentEntries) {
15
+ const latestEntry = getLatestVersion(agentEntries);
16
+ return {
17
+ slug,
18
+ name: manifest.name,
19
+ latestVersion: latestEntry.version,
20
+ totalVersions: agentEntries.length,
21
+ description: manifest.description,
22
+ author: manifest.author,
23
+ runtime: manifest.runtime,
24
+ includes: manifest.includes,
25
+ requirements: manifest.requirements,
26
+ metadata: manifest.metadata,
27
+ downloads: manifest.downloads || 0,
28
+ stars: manifest.stats?.stars || 0,
29
+ rating: manifest.stats?.rating || null,
30
+ };
31
+ }
32
+
33
+ export async function statsCommand(agentSpec, options = {}) {
34
+ const { slug } = parseSpec(agentSpec);
35
+
36
+ if (!options.registry) {
37
+ const [manifest, agentsResult] = await Promise.all([
38
+ fetchRemoteJson(`/api/agents/${slug}`, options),
39
+ fetchRemoteJson(`/api/agents?q=${encodeURIComponent(slug)}`, options),
40
+ ]);
41
+
42
+ const agentEntries = (agentsResult.agents || []).filter((entry) => entry.slug === slug);
43
+ if (agentEntries.length === 0) {
44
+ throw new Error(`Agent not found: ${slug}`);
45
+ }
46
+
47
+ return buildStatsResult(slug, manifest, agentEntries);
48
+ }
49
+
50
+ const registryDir = path.resolve(options.registry);
51
+ const indexPath = path.join(registryDir, "index.json");
52
+ if (!(await pathExists(indexPath))) {
53
+ throw new Error(`Agent not found: ${slug}`);
54
+ }
55
+
56
+ const index = await readJson(indexPath);
57
+ const agentEntries = index.agents.filter((entry) => entry.slug === slug);
58
+
59
+ if (agentEntries.length === 0) {
60
+ throw new Error(`Agent not found: ${slug}`);
61
+ }
62
+
63
+ const latestEntry = getLatestVersion(agentEntries);
64
+ const manifestPath = path.join(
65
+ registryDir,
66
+ "agents",
67
+ slug,
68
+ latestEntry.version,
69
+ "MANIFEST.json"
70
+ );
71
+ const manifest = await readJson(manifestPath);
72
+
73
+ return buildStatsResult(slug, manifest, agentEntries);
74
+ }
75
+
76
+ export function formatStatsOutput(stats) {
77
+ const lines = [];
78
+ lines.push("\n╔═══════════════════════════════════════════════════════════════╗");
79
+ lines.push("║ Agent Statistics ║");
80
+ lines.push("╠═══════════════════════════════════════════════════════════════╣");
81
+ lines.push(`║ Name: ${stats.name.substring(0, 44).padEnd(44)}║`);
82
+ lines.push(`║ Slug: ${stats.slug.padEnd(44)}║`);
83
+ lines.push(`║ Version: ${stats.latestVersion.padEnd(44)}║`);
84
+ lines.push(`║ Author: ${(stats.author || "unknown").padEnd(44)}║`);
85
+ lines.push("╠═══════════════════════════════════════════════════════════════╣");
86
+ lines.push("║ Statistics: ║");
87
+ lines.push(`║ Downloads: ${String(stats.downloads).padEnd(44)}║`);
88
+ lines.push(`║ Stars: ${String(stats.stars).padEnd(44)}║`);
89
+ lines.push(`║ Versions: ${String(stats.totalVersions).padEnd(44)}║`);
90
+ if (stats.rating) {
91
+ lines.push(`║ Rating: ${`${stats.rating}/5.0`.padEnd(44)}║`);
92
+ }
93
+ lines.push("╠═══════════════════════════════════════════════════════════════╣");
94
+ lines.push("║ Content: ║");
95
+ const memory = stats.includes?.memory || {};
96
+ lines.push(`║ Memory: ${`共 ${memory.count || 0} 条 (public: ${memory.public || 0}, portable: ${memory.portable || 0})`.padEnd(42)}║`);
97
+ if (stats.includes?.skills?.length > 0) {
98
+ lines.push(`║ Skills: ${stats.includes.skills.join(", ").substring(0, 42).padEnd(42)}║`);
99
+ }
100
+ lines.push("╠═══════════════════════════════════════════════════════════════╣");
101
+ lines.push(`║ Runtime: ${`${stats.runtime?.type || "openclaw"} ${stats.runtime?.version || ""}`.padEnd(44)}║`);
102
+ lines.push("╚═══════════════════════════════════════════════════════════════╝");
103
+
104
+ return lines.join("\n");
105
+ }
@@ -1,76 +1,76 @@
1
- /**
2
- * Uninstall Command
3
- * 卸载已安装的 Agent
4
- */
5
-
6
- import path from "node:path";
7
- import { pathExists, readJson, writeJson, removeDir } from "../lib/fs-utils.js";
8
-
9
- /**
10
- * 卸载已安装的 Agent
11
- * @param {string} agentSpec - Agent slug 或 slug@version
12
- * @param {object} options - 选项
13
- * @returns {Promise<object>} 卸载结果
14
- */
15
- export async function uninstallCommand(agentSpec, options = {}) {
16
- const { slug } = parseSpec(agentSpec);
17
- const targetWorkspace = path.resolve(options.targetWorkspace || process.cwd());
18
- const agenthubDir = path.join(targetWorkspace, ".agenthub");
19
- const installRecordPath = path.join(agenthubDir, "install.json");
20
-
21
- // 检查安装记录是否存在
22
- if (!(await pathExists(installRecordPath))) {
23
- throw new Error(`未找到安装记录: ${slug}\n 该 Agent 可能未安装或安装记录已损坏`);
24
- }
25
-
26
- // 读取安装记录
27
- const installRecord = await readJson(installRecordPath);
28
-
29
- // 检查是否是该 Agent
30
- if (installRecord.slug !== slug) {
31
- throw new Error(`当前工作区安装的是 ${installRecord.slug},而非 ${slug}`);
32
- }
33
-
34
- // 保存卸载信息
35
- const uninstallInfo = {
36
- slug: installRecord.slug,
37
- version: installRecord.version,
38
- installedAt: installRecord.installedAt,
39
- uninstalledAt: new Date().toISOString(),
40
- location: targetWorkspace,
41
- };
42
-
43
- // 删除安装记录
44
- await removeDir(agenthubDir);
45
-
46
- return uninstallInfo;
47
- }
48
-
49
- /**
50
- * 解析 agent spec
51
- */
52
- function parseSpec(spec) {
53
- const match = spec.match(/^([^@]+)(?:@(.+))?$/);
54
- if (!match) {
55
- throw new Error(`无效的 agent spec: ${spec}`);
56
- }
57
- return {
58
- slug: match[1],
59
- version: match[2] || null,
60
- };
61
- }
62
-
63
- /**
64
- * 格式化卸载输出
65
- */
66
- export function formatUninstallOutput(info) {
67
- const lines = [];
68
- lines.push("\n🗑️ 卸载成功\n");
69
- lines.push("─".repeat(50));
70
- lines.push(` Agent: ${info.slug}@${info.version}`);
71
- lines.push(` 安装时间: ${info.installedAt || "未知"}`);
72
- lines.push(` 卸载时间: ${info.uninstalledAt}`);
73
- lines.push("─".repeat(50));
74
- lines.push(`\n💡 重新安装: agenthub install ${info.slug}\n`);
75
- return lines.join("\n");
76
- }
1
+ /**
2
+ * Uninstall Command
3
+ * 卸载已安装的 Agent
4
+ */
5
+
6
+ import path from "node:path";
7
+ import { pathExists, readJson, writeJson, removeDir } from "../lib/fs-utils.js";
8
+
9
+ /**
10
+ * 卸载已安装的 Agent
11
+ * @param {string} agentSpec - Agent slug 或 slug@version
12
+ * @param {object} options - 选项
13
+ * @returns {Promise<object>} 卸载结果
14
+ */
15
+ export async function uninstallCommand(agentSpec, options = {}) {
16
+ const { slug } = parseSpec(agentSpec);
17
+ const targetWorkspace = path.resolve(options.targetWorkspace || process.cwd());
18
+ const agenthubDir = path.join(targetWorkspace, ".agenthub");
19
+ const installRecordPath = path.join(agenthubDir, "install.json");
20
+
21
+ // 检查安装记录是否存在
22
+ if (!(await pathExists(installRecordPath))) {
23
+ throw new Error(`未找到安装记录: ${slug}\n 该 Agent 可能未安装或安装记录已损坏`);
24
+ }
25
+
26
+ // 读取安装记录
27
+ const installRecord = await readJson(installRecordPath);
28
+
29
+ // 检查是否是该 Agent
30
+ if (installRecord.slug !== slug) {
31
+ throw new Error(`当前工作区安装的是 ${installRecord.slug},而非 ${slug}`);
32
+ }
33
+
34
+ // 保存卸载信息
35
+ const uninstallInfo = {
36
+ slug: installRecord.slug,
37
+ version: installRecord.version,
38
+ installedAt: installRecord.installedAt,
39
+ uninstalledAt: new Date().toISOString(),
40
+ location: targetWorkspace,
41
+ };
42
+
43
+ // 删除安装记录
44
+ await removeDir(agenthubDir);
45
+
46
+ return uninstallInfo;
47
+ }
48
+
49
+ /**
50
+ * 解析 agent spec
51
+ */
52
+ function parseSpec(spec) {
53
+ const match = spec.match(/^([^@]+)(?:@(.+))?$/);
54
+ if (!match) {
55
+ throw new Error(`无效的 agent spec: ${spec}`);
56
+ }
57
+ return {
58
+ slug: match[1],
59
+ version: match[2] || null,
60
+ };
61
+ }
62
+
63
+ /**
64
+ * 格式化卸载输出
65
+ */
66
+ export function formatUninstallOutput(info) {
67
+ const lines = [];
68
+ lines.push("\n🗑️ 卸载成功\n");
69
+ lines.push("─".repeat(50));
70
+ lines.push(` Agent: ${info.slug}@${info.version}`);
71
+ lines.push(` 安装时间: ${info.installedAt || "未知"}`);
72
+ lines.push(` 卸载时间: ${info.uninstalledAt}`);
73
+ lines.push("─".repeat(50));
74
+ lines.push(`\n💡 重新安装: agenthub install ${info.slug}\n`);
75
+ return lines.join("\n");
76
+ }
@@ -1,54 +1,54 @@
1
- /**
2
- * Update Command
3
- * 更新已安装的 Agent 到最新版本
4
- */
5
-
6
- import path from "node:path";
7
- import { getCurrentVersion, performVersionChange } from "../lib/version-manager.js";
8
- import { parseSpec } from "../lib/registry.js";
9
- import { versionsCommand } from "./versions.js";
10
- import { success, warning, highlight, muted, symbols } from "../lib/colors.js";
11
-
12
- export async function updateCommand(agentSpec, options = {}) {
13
- const targetWorkspace = options.targetWorkspace ? path.resolve(options.targetWorkspace) : null;
14
- const { slug } = parseSpec(agentSpec);
15
-
16
- // 获取可用版本
17
- const versions = await versionsCommand(slug, options);
18
- if (versions.length === 0) {
19
- throw new Error(`Agent not found: ${slug}`);
20
- }
21
-
22
- const latestVersion = versions[0].version;
23
-
24
- // 获取当前安装版本
25
- const currentVersion = await getCurrentVersion(targetWorkspace);
26
-
27
- if (currentVersion === latestVersion) {
28
- return {
29
- updated: false,
30
- message: `${success(`${symbols.success} ${slug} 已是最新版本`)} ${muted(`(${latestVersion})`)}`,
31
- currentVersion,
32
- latestVersion,
33
- };
34
- }
35
-
36
- // 执行更新
37
- const result = await performVersionChange(slug, latestVersion, currentVersion, targetWorkspace, options);
38
-
39
- return {
40
- updated: true,
41
- message: [
42
- success(`${symbols.success} 更新成功`),
43
- "",
44
- ` ${highlight("Agent:")} ${slug}`,
45
- ` ${muted("旧版本:")} ${currentVersion || "未知"}`,
46
- ` ${highlight("新版本:")} ${latestVersion}`,
47
- "",
48
- ` ${muted("运行")} ${highlight("agenthub verify " + slug)} ${muted("校验安装状态")}`,
49
- ].join("\n"),
50
- currentVersion: latestVersion,
51
- previousVersion: currentVersion,
52
- manifest: result.manifest,
53
- };
54
- }
1
+ /**
2
+ * Update Command
3
+ * 更新已安装的 Agent 到最新版本
4
+ */
5
+
6
+ import path from "node:path";
7
+ import { getCurrentVersion, performVersionChange } from "../lib/version-manager.js";
8
+ import { parseSpec } from "../lib/registry.js";
9
+ import { versionsCommand } from "./versions.js";
10
+ import { success, warning, highlight, muted, symbols } from "../lib/colors.js";
11
+
12
+ export async function updateCommand(agentSpec, options = {}) {
13
+ const targetWorkspace = options.targetWorkspace ? path.resolve(options.targetWorkspace) : null;
14
+ const { slug } = parseSpec(agentSpec);
15
+
16
+ // 获取可用版本
17
+ const versions = await versionsCommand(slug, options);
18
+ if (versions.length === 0) {
19
+ throw new Error(`Agent not found: ${slug}`);
20
+ }
21
+
22
+ const latestVersion = versions[0].version;
23
+
24
+ // 获取当前安装版本
25
+ const currentVersion = await getCurrentVersion(targetWorkspace);
26
+
27
+ if (currentVersion === latestVersion) {
28
+ return {
29
+ updated: false,
30
+ message: `${success(`${symbols.success} ${slug} 已是最新版本`)} ${muted(`(${latestVersion})`)}`,
31
+ currentVersion,
32
+ latestVersion,
33
+ };
34
+ }
35
+
36
+ // 执行更新
37
+ const result = await performVersionChange(slug, latestVersion, currentVersion, targetWorkspace, options);
38
+
39
+ return {
40
+ updated: true,
41
+ message: [
42
+ success(`${symbols.success} 更新成功`),
43
+ "",
44
+ ` ${highlight("Agent:")} ${slug}`,
45
+ ` ${muted("旧版本:")} ${currentVersion || "未知"}`,
46
+ ` ${highlight("新版本:")} ${latestVersion}`,
47
+ "",
48
+ ` ${muted("运行")} ${highlight("agenthub verify " + slug)} ${muted("校验安装状态")}`,
49
+ ].join("\n"),
50
+ currentVersion: latestVersion,
51
+ previousVersion: currentVersion,
52
+ manifest: result.manifest,
53
+ };
54
+ }