@agents-uni/core 0.1.0
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/DESIGN.md +283 -0
- package/LICENSE +21 -0
- package/README.en.md +589 -0
- package/README.md +589 -0
- package/dist/bridge/config-sync.d.ts +24 -0
- package/dist/bridge/config-sync.d.ts.map +1 -0
- package/dist/bridge/config-sync.js +39 -0
- package/dist/bridge/config-sync.js.map +1 -0
- package/dist/bridge/index.d.ts +7 -0
- package/dist/bridge/index.d.ts.map +1 -0
- package/dist/bridge/index.js +7 -0
- package/dist/bridge/index.js.map +1 -0
- package/dist/bridge/openclaw-adapter.d.ts +49 -0
- package/dist/bridge/openclaw-adapter.d.ts.map +1 -0
- package/dist/bridge/openclaw-adapter.js +151 -0
- package/dist/bridge/openclaw-adapter.js.map +1 -0
- package/dist/bridge/soul-generator.d.ts +34 -0
- package/dist/bridge/soul-generator.d.ts.map +1 -0
- package/dist/bridge/soul-generator.js +149 -0
- package/dist/bridge/soul-generator.js.map +1 -0
- package/dist/bridge/task-dispatcher.d.ts +107 -0
- package/dist/bridge/task-dispatcher.d.ts.map +1 -0
- package/dist/bridge/task-dispatcher.js +217 -0
- package/dist/bridge/task-dispatcher.js.map +1 -0
- package/dist/bridge/uni-registry.d.ts +82 -0
- package/dist/bridge/uni-registry.d.ts.map +1 -0
- package/dist/bridge/uni-registry.js +261 -0
- package/dist/bridge/uni-registry.js.map +1 -0
- package/dist/bridge/workspace-io.d.ts +64 -0
- package/dist/bridge/workspace-io.d.ts.map +1 -0
- package/dist/bridge/workspace-io.js +99 -0
- package/dist/bridge/workspace-io.js.map +1 -0
- package/dist/cli/commands/deploy.d.ts +6 -0
- package/dist/cli/commands/deploy.d.ts.map +1 -0
- package/dist/cli/commands/deploy.js +48 -0
- package/dist/cli/commands/deploy.js.map +1 -0
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +137 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/inspect.d.ts +4 -0
- package/dist/cli/commands/inspect.d.ts.map +1 -0
- package/dist/cli/commands/inspect.js +77 -0
- package/dist/cli/commands/inspect.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +2 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +30 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/commands/visualize.d.ts +2 -0
- package/dist/cli/commands/visualize.d.ts.map +1 -0
- package/dist/cli/commands/visualize.js +69 -0
- package/dist/cli/commands/visualize.js.map +1 -0
- package/dist/cli/index.d.ts +6 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +132 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/agent-registry.d.ts +37 -0
- package/dist/core/agent-registry.d.ts.map +1 -0
- package/dist/core/agent-registry.js +97 -0
- package/dist/core/agent-registry.js.map +1 -0
- package/dist/core/event-bus.d.ts +34 -0
- package/dist/core/event-bus.d.ts.map +1 -0
- package/dist/core/event-bus.js +96 -0
- package/dist/core/event-bus.js.map +1 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +8 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/permission-matrix.d.ts +35 -0
- package/dist/core/permission-matrix.d.ts.map +1 -0
- package/dist/core/permission-matrix.js +95 -0
- package/dist/core/permission-matrix.js.map +1 -0
- package/dist/core/relationship-graph.d.ts +50 -0
- package/dist/core/relationship-graph.d.ts.map +1 -0
- package/dist/core/relationship-graph.js +150 -0
- package/dist/core/relationship-graph.js.map +1 -0
- package/dist/core/resource-pool.d.ts +48 -0
- package/dist/core/resource-pool.d.ts.map +1 -0
- package/dist/core/resource-pool.js +205 -0
- package/dist/core/resource-pool.js.map +1 -0
- package/dist/core/state-machine.d.ts +47 -0
- package/dist/core/state-machine.d.ts.map +1 -0
- package/dist/core/state-machine.js +110 -0
- package/dist/core/state-machine.js.map +1 -0
- package/dist/core/universe.d.ts +38 -0
- package/dist/core/universe.d.ts.map +1 -0
- package/dist/core/universe.js +101 -0
- package/dist/core/universe.js.map +1 -0
- package/dist/dashboard/api.d.ts +10 -0
- package/dist/dashboard/api.d.ts.map +1 -0
- package/dist/dashboard/api.js +237 -0
- package/dist/dashboard/api.js.map +1 -0
- package/dist/dashboard/index.d.ts +3 -0
- package/dist/dashboard/index.d.ts.map +1 -0
- package/dist/dashboard/index.js +3 -0
- package/dist/dashboard/index.js.map +1 -0
- package/dist/dashboard/server.d.ts +31 -0
- package/dist/dashboard/server.d.ts.map +1 -0
- package/dist/dashboard/server.js +44 -0
- package/dist/dashboard/server.js.map +1 -0
- package/dist/dashboard/templates.d.ts +47 -0
- package/dist/dashboard/templates.d.ts.map +1 -0
- package/dist/dashboard/templates.js +1481 -0
- package/dist/dashboard/templates.js.map +1 -0
- package/dist/evolution/index.d.ts +5 -0
- package/dist/evolution/index.d.ts.map +1 -0
- package/dist/evolution/index.js +5 -0
- package/dist/evolution/index.js.map +1 -0
- package/dist/evolution/memory-consolidator.d.ts +28 -0
- package/dist/evolution/memory-consolidator.d.ts.map +1 -0
- package/dist/evolution/memory-consolidator.js +84 -0
- package/dist/evolution/memory-consolidator.js.map +1 -0
- package/dist/evolution/performance-tracker.d.ts +29 -0
- package/dist/evolution/performance-tracker.d.ts.map +1 -0
- package/dist/evolution/performance-tracker.js +90 -0
- package/dist/evolution/performance-tracker.js.map +1 -0
- package/dist/evolution/promotion-engine.d.ts +32 -0
- package/dist/evolution/promotion-engine.d.ts.map +1 -0
- package/dist/evolution/promotion-engine.js +117 -0
- package/dist/evolution/promotion-engine.js.map +1 -0
- package/dist/evolution/relationship-evolver.d.ts +40 -0
- package/dist/evolution/relationship-evolver.d.ts.map +1 -0
- package/dist/evolution/relationship-evolver.js +105 -0
- package/dist/evolution/relationship-evolver.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/schema/index.d.ts +13 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +18 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/universe.schema.json +214 -0
- package/dist/spec/compiler.d.ts +16 -0
- package/dist/spec/compiler.d.ts.map +1 -0
- package/dist/spec/compiler.js +26 -0
- package/dist/spec/compiler.js.map +1 -0
- package/dist/spec/index.d.ts +4 -0
- package/dist/spec/index.d.ts.map +1 -0
- package/dist/spec/index.js +4 -0
- package/dist/spec/index.js.map +1 -0
- package/dist/spec/parser.d.ts +11 -0
- package/dist/spec/parser.d.ts.map +1 -0
- package/dist/spec/parser.js +89 -0
- package/dist/spec/parser.js.map +1 -0
- package/dist/spec/validator.d.ts +9 -0
- package/dist/spec/validator.d.ts.map +1 -0
- package/dist/spec/validator.js +105 -0
- package/dist/spec/validator.js.map +1 -0
- package/dist/types/agent.d.ts +56 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +8 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/event.d.ts +34 -0
- package/dist/types/event.d.ts.map +1 -0
- package/dist/types/event.js +11 -0
- package/dist/types/event.js.map +1 -0
- package/dist/types/governance.d.ts +48 -0
- package/dist/types/governance.d.ts.map +1 -0
- package/dist/types/governance.js +9 -0
- package/dist/types/governance.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +9 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/memory.d.ts +73 -0
- package/dist/types/memory.d.ts.map +1 -0
- package/dist/types/memory.js +9 -0
- package/dist/types/memory.js.map +1 -0
- package/dist/types/protocol.d.ts +48 -0
- package/dist/types/protocol.d.ts.map +1 -0
- package/dist/types/protocol.js +9 -0
- package/dist/types/protocol.js.map +1 -0
- package/dist/types/relationship.d.ts +40 -0
- package/dist/types/relationship.d.ts.map +1 -0
- package/dist/types/relationship.js +9 -0
- package/dist/types/relationship.js.map +1 -0
- package/dist/types/resource.d.ts +52 -0
- package/dist/types/resource.d.ts.map +1 -0
- package/dist/types/resource.js +9 -0
- package/dist/types/resource.js.map +1 -0
- package/dist/types/universe.d.ts +71 -0
- package/dist/types/universe.d.ts.map +1 -0
- package/dist/types/universe.js +9 -0
- package/dist/types/universe.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,1481 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dashboard HTML Templates — server-side rendered pages.
|
|
3
|
+
*
|
|
4
|
+
* Uses Tailwind CDN for styling. No frontend framework needed.
|
|
5
|
+
* All functions return HTML strings.
|
|
6
|
+
*/
|
|
7
|
+
// ─── Layout ───────────────────────────────────────
|
|
8
|
+
export function renderLayout(title, bodyHtml, activeNav) {
|
|
9
|
+
return `<!DOCTYPE html>
|
|
10
|
+
<html lang="zh-CN" class="dark">
|
|
11
|
+
<head>
|
|
12
|
+
<meta charset="UTF-8">
|
|
13
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
14
|
+
<title>${escapeHtml(title)} — Uni Dashboard</title>
|
|
15
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
16
|
+
<script>
|
|
17
|
+
tailwind.config = {
|
|
18
|
+
darkMode: 'class',
|
|
19
|
+
theme: {
|
|
20
|
+
extend: {
|
|
21
|
+
colors: {
|
|
22
|
+
surface: { DEFAULT: '#0f172a', light: '#1e293b', lighter: '#334155' },
|
|
23
|
+
accent: { DEFAULT: '#818cf8', light: '#a5b4fc', dark: '#6366f1' },
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
</script>
|
|
29
|
+
<style>
|
|
30
|
+
body { font-family: 'Inter', system-ui, -apple-system, sans-serif; }
|
|
31
|
+
.card-hover { transition: transform 0.15s, box-shadow 0.15s; }
|
|
32
|
+
.card-hover:hover { transform: translateY(-2px); box-shadow: 0 8px 25px rgba(0,0,0,0.3); }
|
|
33
|
+
.badge { display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 9999px; font-size: 0.75rem; font-weight: 500; }
|
|
34
|
+
.glow { box-shadow: 0 0 20px rgba(129, 140, 248, 0.15); }
|
|
35
|
+
.gradient-text { background: linear-gradient(135deg, #818cf8, #c084fc); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
|
|
36
|
+
@keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
|
|
37
|
+
.animate-in { animation: fadeIn 0.4s ease-out forwards; }
|
|
38
|
+
.animate-in-delay-1 { animation-delay: 0.1s; opacity: 0; }
|
|
39
|
+
.animate-in-delay-2 { animation-delay: 0.2s; opacity: 0; }
|
|
40
|
+
.animate-in-delay-3 { animation-delay: 0.3s; opacity: 0; }
|
|
41
|
+
</style>
|
|
42
|
+
</head>
|
|
43
|
+
<body class="bg-surface text-gray-200 min-h-screen">
|
|
44
|
+
<!-- Navigation -->
|
|
45
|
+
<nav class="bg-surface-light border-b border-gray-700/50 sticky top-0 z-50">
|
|
46
|
+
<div class="max-w-7xl mx-auto px-6 py-3 flex items-center justify-between">
|
|
47
|
+
<a href="/" class="flex items-center gap-3 text-white hover:text-accent-light transition">
|
|
48
|
+
<span class="text-2xl">🌌</span>
|
|
49
|
+
<span class="font-bold text-lg">Uni Dashboard</span>
|
|
50
|
+
</a>
|
|
51
|
+
<div class="flex items-center gap-6 text-sm">
|
|
52
|
+
<a href="/" class="${activeNav === 'home' ? 'text-accent-light' : 'text-gray-400 hover:text-white'} transition">首页</a>
|
|
53
|
+
<a href="/manage" class="${activeNav === 'manage' ? 'text-accent-light' : 'text-gray-400 hover:text-white'} transition">管理</a>
|
|
54
|
+
<a href="/guide" class="${activeNav === 'guide' ? 'text-accent-light' : 'text-gray-400 hover:text-white'} transition">手册</a>
|
|
55
|
+
<a href="/api/health" class="text-gray-400 hover:text-white transition">API</a>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</nav>
|
|
59
|
+
|
|
60
|
+
<!-- Content -->
|
|
61
|
+
<main class="max-w-7xl mx-auto px-6 py-8">
|
|
62
|
+
${bodyHtml}
|
|
63
|
+
</main>
|
|
64
|
+
|
|
65
|
+
<!-- Footer -->
|
|
66
|
+
<footer class="border-t border-gray-700/50 mt-16 py-6 text-center text-gray-500 text-sm">
|
|
67
|
+
@agents-uni/core Dashboard · Powered by Hono
|
|
68
|
+
</footer>
|
|
69
|
+
</body>
|
|
70
|
+
</html>`;
|
|
71
|
+
}
|
|
72
|
+
export function renderHomePage(unis, stats, extensionPanels) {
|
|
73
|
+
const typeColors = {
|
|
74
|
+
hierarchical: 'bg-blue-500/20 text-blue-300',
|
|
75
|
+
flat: 'bg-green-500/20 text-green-300',
|
|
76
|
+
competitive: 'bg-red-500/20 text-red-300',
|
|
77
|
+
hybrid: 'bg-purple-500/20 text-purple-300',
|
|
78
|
+
};
|
|
79
|
+
// ─── Hero Section ─────────────────────────────
|
|
80
|
+
const heroHtml = `
|
|
81
|
+
<div class="text-center py-12 mb-8 animate-in">
|
|
82
|
+
<div class="text-6xl mb-6">🌌</div>
|
|
83
|
+
<h1 class="text-4xl md:text-5xl font-bold mb-4">
|
|
84
|
+
<span class="gradient-text">Uni Dashboard</span>
|
|
85
|
+
</h1>
|
|
86
|
+
<p class="text-gray-400 text-lg max-w-2xl mx-auto mb-6">
|
|
87
|
+
Agent 组织管理与监控中心 — 查看已部署的 Agent、它们之间的关系、管理多个 Uni 的生命周期
|
|
88
|
+
</p>
|
|
89
|
+
<div class="flex justify-center gap-4 text-sm">
|
|
90
|
+
<a href="/guide" class="px-5 py-2.5 bg-accent/20 text-accent-light rounded-lg hover:bg-accent/30 transition border border-accent/30">
|
|
91
|
+
📖 用户手册
|
|
92
|
+
</a>
|
|
93
|
+
<a href="/manage" class="px-5 py-2.5 bg-surface-light text-gray-300 rounded-lg hover:bg-surface-lighter transition border border-gray-700/50">
|
|
94
|
+
⚙️ 管理中心
|
|
95
|
+
</a>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
`;
|
|
99
|
+
// ─── Quick Start ──────────────────────────────
|
|
100
|
+
const quickStartHtml = unis.length === 0 ? `
|
|
101
|
+
<div class="bg-surface-light rounded-xl p-8 border border-gray-700/50 mb-8 animate-in animate-in-delay-1">
|
|
102
|
+
<h2 class="text-xl font-semibold text-white mb-4">🚀 快速开始</h2>
|
|
103
|
+
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 text-sm">
|
|
104
|
+
<div class="space-y-2">
|
|
105
|
+
<div class="text-accent-light font-medium">Step 1: 定义 Universe</div>
|
|
106
|
+
<p class="text-gray-400">创建 <code class="bg-surface px-1.5 py-0.5 rounded text-accent-light text-xs">universe.yaml</code> 描述你的 Agent 组织结构</p>
|
|
107
|
+
</div>
|
|
108
|
+
<div class="space-y-2">
|
|
109
|
+
<div class="text-accent-light font-medium">Step 2: 部署</div>
|
|
110
|
+
<p class="text-gray-400">运行 <code class="bg-surface px-1.5 py-0.5 rounded text-accent-light text-xs">uni deploy universe.yaml</code></p>
|
|
111
|
+
</div>
|
|
112
|
+
<div class="space-y-2">
|
|
113
|
+
<div class="text-accent-light font-medium">Step 3: 监控</div>
|
|
114
|
+
<p class="text-gray-400">回到此页面查看 Agent 状态和关系</p>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
` : '';
|
|
119
|
+
// ─── Stats Section ────────────────────────────
|
|
120
|
+
const statsHtml = stats.totalUnis > 0 ? `
|
|
121
|
+
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8 animate-in animate-in-delay-1">
|
|
122
|
+
<div class="bg-surface-light rounded-xl p-5 border border-gray-700/50 glow">
|
|
123
|
+
<div class="text-3xl font-bold text-white">${stats.totalUnis}</div>
|
|
124
|
+
<div class="text-gray-400 text-sm mt-1">已部署 Uni</div>
|
|
125
|
+
</div>
|
|
126
|
+
<div class="bg-surface-light rounded-xl p-5 border border-gray-700/50">
|
|
127
|
+
<div class="text-3xl font-bold text-white">${stats.totalAgents}</div>
|
|
128
|
+
<div class="text-gray-400 text-sm mt-1">总 Agent 数</div>
|
|
129
|
+
</div>
|
|
130
|
+
${Object.entries(stats.uniTypes).map(([type, count]) => `
|
|
131
|
+
<div class="bg-surface-light rounded-xl p-5 border border-gray-700/50">
|
|
132
|
+
<div class="text-3xl font-bold text-white">${count}</div>
|
|
133
|
+
<div class="text-gray-400 text-sm mt-1">${type} 类型</div>
|
|
134
|
+
</div>
|
|
135
|
+
`).join('')}
|
|
136
|
+
</div>
|
|
137
|
+
` : '';
|
|
138
|
+
// ─── Uni Cards ────────────────────────────────
|
|
139
|
+
const unisHtml = unis.length === 0
|
|
140
|
+
? `<div class="text-center py-16 animate-in animate-in-delay-2">
|
|
141
|
+
<div class="text-5xl mb-4">🌑</div>
|
|
142
|
+
<h2 class="text-xl text-gray-400 mb-2">尚无已部署的 Uni</h2>
|
|
143
|
+
<p class="text-gray-500">运行 <code class="bg-surface-lighter px-2 py-1 rounded text-accent-light">uni deploy universe.yaml</code> 来部署你的第一个 Uni</p>
|
|
144
|
+
</div>`
|
|
145
|
+
: `
|
|
146
|
+
<div class="mb-6 animate-in animate-in-delay-2">
|
|
147
|
+
<h2 class="text-xl font-semibold text-white">已部署的 Uni</h2>
|
|
148
|
+
</div>
|
|
149
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 animate-in animate-in-delay-2">
|
|
150
|
+
${unis.map(uni => `
|
|
151
|
+
<a href="/uni/${encodeURIComponent(uni.id)}" class="card-hover bg-surface-light rounded-xl p-6 border border-gray-700/50 block">
|
|
152
|
+
<div class="flex items-start justify-between mb-3">
|
|
153
|
+
<h3 class="font-semibold text-white text-lg">${escapeHtml(uni.id)}</h3>
|
|
154
|
+
<span class="badge ${typeColors[uni.type] ?? 'bg-gray-500/20 text-gray-300'}">${uni.type}</span>
|
|
155
|
+
</div>
|
|
156
|
+
<p class="text-gray-400 text-sm mb-4 line-clamp-2">${escapeHtml(uni.description)}</p>
|
|
157
|
+
<div class="flex items-center justify-between text-xs text-gray-500">
|
|
158
|
+
<span>🤖 ${uni.agentIds.length} agents</span>
|
|
159
|
+
<span>v${escapeHtml(uni.version)}</span>
|
|
160
|
+
</div>
|
|
161
|
+
<div class="mt-3 text-xs text-gray-600">
|
|
162
|
+
部署于 ${formatDate(uni.deployedAt)}
|
|
163
|
+
</div>
|
|
164
|
+
</a>
|
|
165
|
+
`).join('')}
|
|
166
|
+
</div>`;
|
|
167
|
+
// ─── Extension Panels ────────────────────────
|
|
168
|
+
const extensionHtml = extensionPanels && extensionPanels.length > 0
|
|
169
|
+
? `
|
|
170
|
+
<div class="mt-10 mb-2 animate-in animate-in-delay-2">
|
|
171
|
+
<h2 class="text-xl font-semibold text-white mb-4">📊 实时数据面板</h2>
|
|
172
|
+
</div>
|
|
173
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 animate-in animate-in-delay-3">
|
|
174
|
+
${extensionPanels.map(panel => `
|
|
175
|
+
<div class="bg-surface-light rounded-xl border border-gray-700/50 overflow-hidden">
|
|
176
|
+
<div class="px-5 py-3 border-b border-gray-700/50 bg-surface-lighter/30">
|
|
177
|
+
<h3 class="text-sm font-semibold text-white">${escapeHtml(panel.title)}</h3>
|
|
178
|
+
</div>
|
|
179
|
+
<div class="p-5">
|
|
180
|
+
${panel.html}
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
`).join('')}
|
|
184
|
+
</div>
|
|
185
|
+
`
|
|
186
|
+
: '';
|
|
187
|
+
// ─── Architecture Overview ────────────────────
|
|
188
|
+
const archHtml = `
|
|
189
|
+
<div class="mt-12 bg-surface-light rounded-xl p-8 border border-gray-700/50 animate-in animate-in-delay-3">
|
|
190
|
+
<h2 class="text-xl font-semibold text-white mb-6">🏗️ 架构概览</h2>
|
|
191
|
+
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 text-sm">
|
|
192
|
+
<div class="bg-surface rounded-xl p-5 border border-gray-700/30">
|
|
193
|
+
<div class="text-2xl mb-3">📐</div>
|
|
194
|
+
<div class="text-white font-medium mb-2">agents-uni-core</div>
|
|
195
|
+
<p class="text-gray-400">通用协议层 — 定义 Agent 组织、关系、治理、进化的规范和运行时</p>
|
|
196
|
+
</div>
|
|
197
|
+
<div class="bg-surface rounded-xl p-5 border border-gray-700/30">
|
|
198
|
+
<div class="text-2xl mb-3">🎭</div>
|
|
199
|
+
<div class="text-white font-medium mb-2">具体 Uni 实例</div>
|
|
200
|
+
<p class="text-gray-400">如 zhenhuan-uni(后宫赛马)、公司制 uni 等 — 基于 core 构建的特化系统</p>
|
|
201
|
+
</div>
|
|
202
|
+
<div class="bg-surface rounded-xl p-5 border border-gray-700/30">
|
|
203
|
+
<div class="text-2xl mb-3">🔗</div>
|
|
204
|
+
<div class="text-white font-medium mb-2">OpenClaw 桥接</div>
|
|
205
|
+
<p class="text-gray-400">通过文件协议(SOUL.md / TASK.md / SUBMISSION.md)与 OpenClaw Agent 通信</p>
|
|
206
|
+
</div>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
`;
|
|
210
|
+
const body = `
|
|
211
|
+
${heroHtml}
|
|
212
|
+
${quickStartHtml}
|
|
213
|
+
${statsHtml}
|
|
214
|
+
${unisHtml}
|
|
215
|
+
${extensionHtml}
|
|
216
|
+
${archHtml}
|
|
217
|
+
`;
|
|
218
|
+
return renderLayout('首页', body, 'home');
|
|
219
|
+
}
|
|
220
|
+
// ─── Guide Page ──────────────────────────────────
|
|
221
|
+
export function renderGuidePage() {
|
|
222
|
+
const codeBlock = (code, lang = '') => `<pre class="bg-surface rounded-lg p-4 border border-gray-700/30 overflow-x-auto text-xs leading-relaxed"><code class="text-gray-300">${escapeHtml(code)}</code></pre>`;
|
|
223
|
+
const body = `
|
|
224
|
+
<div class="mb-8">
|
|
225
|
+
<a href="/" class="text-gray-500 hover:text-gray-300 text-sm transition">← 返回首页</a>
|
|
226
|
+
</div>
|
|
227
|
+
|
|
228
|
+
<h1 class="text-3xl font-bold text-white mb-2">📖 用户手册</h1>
|
|
229
|
+
<p class="text-gray-400 mb-4">从零开始了解 Uni 系统的完整指南 — 事无巨细版</p>
|
|
230
|
+
|
|
231
|
+
<!-- TOC -->
|
|
232
|
+
<div class="bg-surface-light rounded-xl p-6 border border-gray-700/50 mb-8">
|
|
233
|
+
<h2 class="text-lg font-semibold text-white mb-3">目录</h2>
|
|
234
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-1 text-sm">
|
|
235
|
+
<a href="#what-is-uni" class="text-accent-light hover:underline py-1">1. 什么是 Uni?</a>
|
|
236
|
+
<a href="#prerequisites" class="text-accent-light hover:underline py-1">2. 前置要求 & 安装</a>
|
|
237
|
+
<a href="#quick-start" class="text-accent-light hover:underline py-1">3. 从零开始:5 分钟快速上手</a>
|
|
238
|
+
<a href="#universe-yaml" class="text-accent-light hover:underline py-1">4. universe.yaml 完整语法</a>
|
|
239
|
+
<a href="#uni-types" class="text-accent-light hover:underline py-1">5. Uni 类型与组织模板</a>
|
|
240
|
+
<a href="#deploy" class="text-accent-light hover:underline py-1">6. 部署到 OpenClaw</a>
|
|
241
|
+
<a href="#openclaw" class="text-accent-light hover:underline py-1">7. OpenClaw 使用指南</a>
|
|
242
|
+
<a href="#file-protocol" class="text-accent-light hover:underline py-1">8. 文件协议详解</a>
|
|
243
|
+
<a href="#directory" class="text-accent-light hover:underline py-1">9. 目录结构一览</a>
|
|
244
|
+
<a href="#cli-uni" class="text-accent-light hover:underline py-1">10. Uni CLI 命令参考</a>
|
|
245
|
+
<a href="#cli-openclaw" class="text-accent-light hover:underline py-1">11. OpenClaw CLI 命令参考</a>
|
|
246
|
+
<a href="#api-ref" class="text-accent-light hover:underline py-1">12. Dashboard REST API</a>
|
|
247
|
+
<a href="#multi-uni" class="text-accent-light hover:underline py-1">13. 多 Uni 管理</a>
|
|
248
|
+
<a href="#lifecycle" class="text-accent-light hover:underline py-1">14. 生命周期:重置 vs 清理 vs 更新</a>
|
|
249
|
+
<a href="#extension" class="text-accent-light hover:underline py-1">15. Dashboard 扩展机制</a>
|
|
250
|
+
<a href="#troubleshooting" class="text-accent-light hover:underline py-1">16. 常见问题排查</a>
|
|
251
|
+
</div>
|
|
252
|
+
</div>
|
|
253
|
+
|
|
254
|
+
<div class="space-y-8">
|
|
255
|
+
|
|
256
|
+
<!-- 1. What is Uni -->
|
|
257
|
+
<div id="what-is-uni" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
258
|
+
<h2 class="text-xl font-semibold text-white mb-4">1. 什么是 Uni?</h2>
|
|
259
|
+
<div class="text-gray-300 text-sm space-y-3">
|
|
260
|
+
<p><strong class="text-white">Uni(Universe)</strong>是一个 Agent 组织的完整定义。当前的多 Agent 框架解决的是<em>生产力</em>问题 — 如何让 Agent 完成任务。但它们忽略了<em>生产关系</em> — Agent 之间如何组织、治理和进化。</p>
|
|
261
|
+
<p>Uni 系统用一个 YAML 文件定义一个完整的 Agent 社会:</p>
|
|
262
|
+
<ul class="space-y-2 ml-4">
|
|
263
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> <strong class="text-white">Agents</strong> — 组织中的成员,每个有 ID、名字、角色(title + duties + permissions)、特征值(traits)</li>
|
|
264
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> <strong class="text-white">Relationships</strong> — 成员之间的有向关系(superior/subordinate/ally/rival/advisor...),带权重</li>
|
|
265
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> <strong class="text-white">Governance</strong> — 决策模型(autocratic/democratic/consensus)、权限矩阵、审批流程</li>
|
|
266
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> <strong class="text-white">Protocols</strong> — 工作流状态机(如赛马流程:announced → competing → judging → rewarded)</li>
|
|
267
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> <strong class="text-white">Resources</strong> — 有限/可再生/位置性资源的定义与分配策略</li>
|
|
268
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> <strong class="text-white">Evolution</strong> — 基于表现的晋升/降级/淘汰规则,绩效窗口和阈值</li>
|
|
269
|
+
</ul>
|
|
270
|
+
<p class="mt-4">Uni 系统分两层:</p>
|
|
271
|
+
<ul class="space-y-2 ml-4">
|
|
272
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> <strong class="text-white">@agents-uni/core</strong> — 通用协议层,定义 YAML 规范、解析器、验证器、运行时引擎、Dashboard、OpenClaw 桥接</li>
|
|
273
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> <strong class="text-white">具体 Uni 实例</strong>(如 zhenhuan-uni)— 基于 core 构建的特化竞争系统,实现 ELO、赛马、品级等领域逻辑</li>
|
|
274
|
+
</ul>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
|
|
278
|
+
<!-- 2. Prerequisites -->
|
|
279
|
+
<div id="prerequisites" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
280
|
+
<h2 class="text-xl font-semibold text-white mb-4">2. 前置要求 & 安装</h2>
|
|
281
|
+
<div class="text-gray-300 text-sm space-y-4">
|
|
282
|
+
<div>
|
|
283
|
+
<div class="text-white font-medium mb-2">必须安装</div>
|
|
284
|
+
<ul class="space-y-1 ml-4">
|
|
285
|
+
<li class="flex gap-2"><span class="text-green-400">✓</span> <strong>Node.js</strong> ≥ 18(推荐 v22+)</li>
|
|
286
|
+
<li class="flex gap-2"><span class="text-green-400">✓</span> <strong>npm</strong> ≥ 9</li>
|
|
287
|
+
<li class="flex gap-2"><span class="text-green-400">✓</span> <strong>OpenClaw</strong> — Agent 运行时。安装方式:<code class="bg-surface px-1.5 py-0.5 rounded text-accent-light text-xs">npm install -g openclaw</code></li>
|
|
288
|
+
</ul>
|
|
289
|
+
</div>
|
|
290
|
+
<div>
|
|
291
|
+
<div class="text-white font-medium mb-2">验证安装</div>
|
|
292
|
+
${codeBlock(`# 检查 Node 版本
|
|
293
|
+
node --version # 应输出 v18+ 或 v22+
|
|
294
|
+
|
|
295
|
+
# 检查 OpenClaw 版本
|
|
296
|
+
openclaw --version # 应输出 2026.x.x
|
|
297
|
+
|
|
298
|
+
# OpenClaw 首次配置(如果还未配置过)
|
|
299
|
+
openclaw config # 交互式向导,设置 API Key 等`)}
|
|
300
|
+
</div>
|
|
301
|
+
<div>
|
|
302
|
+
<div class="text-white font-medium mb-2">安装 agents-uni-core</div>
|
|
303
|
+
${codeBlock(`# 作为 npm 包安装(如果你要开发自己的 Uni)
|
|
304
|
+
npm install @agents-uni/core
|
|
305
|
+
|
|
306
|
+
# 或者克隆源码
|
|
307
|
+
git clone <repo-url>
|
|
308
|
+
cd agents-uni-core && npm install`)}
|
|
309
|
+
</div>
|
|
310
|
+
</div>
|
|
311
|
+
</div>
|
|
312
|
+
|
|
313
|
+
<!-- 3. Quick Start -->
|
|
314
|
+
<div id="quick-start" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
315
|
+
<h2 class="text-xl font-semibold text-white mb-4">3. 从零开始:5 分钟快速上手</h2>
|
|
316
|
+
<div class="text-sm space-y-5">
|
|
317
|
+
<div class="flex gap-4 items-start">
|
|
318
|
+
<div class="w-8 h-8 rounded-full bg-accent/20 text-accent-light flex items-center justify-center font-bold flex-shrink-0">1</div>
|
|
319
|
+
<div class="flex-1">
|
|
320
|
+
<div class="text-white font-medium">创建项目</div>
|
|
321
|
+
${codeBlock(`# 脚手架创建新 Uni 项目(可选模板:competitive / corporation / flat / government / military)
|
|
322
|
+
npx create-uni my-universe --template competitive
|
|
323
|
+
cd my-universe`)}
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
<div class="flex gap-4 items-start">
|
|
327
|
+
<div class="w-8 h-8 rounded-full bg-accent/20 text-accent-light flex items-center justify-center font-bold flex-shrink-0">2</div>
|
|
328
|
+
<div class="flex-1">
|
|
329
|
+
<div class="text-white font-medium">编辑 universe.yaml</div>
|
|
330
|
+
<p class="text-gray-400 mt-1 mb-2">定义你的 Agent 组织。下面是一个最简示例:</p>
|
|
331
|
+
${codeBlock(`name: my-team
|
|
332
|
+
type: corporation
|
|
333
|
+
version: "0.1.0"
|
|
334
|
+
description: 一个敏捷开发团队
|
|
335
|
+
|
|
336
|
+
agents:
|
|
337
|
+
- id: tech-lead
|
|
338
|
+
name: 技术负责人
|
|
339
|
+
role:
|
|
340
|
+
title: Technical Lead
|
|
341
|
+
duties: [架构设计, 代码审查]
|
|
342
|
+
permissions: [approve, reject]
|
|
343
|
+
rank: 80
|
|
344
|
+
|
|
345
|
+
- id: dev-alpha
|
|
346
|
+
name: 开发者 Alpha
|
|
347
|
+
role:
|
|
348
|
+
title: Software Engineer
|
|
349
|
+
duties: [功能开发, 测试]
|
|
350
|
+
permissions: [call]
|
|
351
|
+
rank: 50
|
|
352
|
+
traits:
|
|
353
|
+
creativity: 0.8
|
|
354
|
+
speed: 0.7
|
|
355
|
+
|
|
356
|
+
relationships:
|
|
357
|
+
- from: tech-lead
|
|
358
|
+
to: dev-alpha
|
|
359
|
+
type: supervises
|
|
360
|
+
weight: 0.9
|
|
361
|
+
|
|
362
|
+
governance:
|
|
363
|
+
decisionModel: autocratic
|
|
364
|
+
permissionMatrix:
|
|
365
|
+
- actor: tech-lead
|
|
366
|
+
target: dev-alpha
|
|
367
|
+
actions: [approve, reject, assign]
|
|
368
|
+
reviewPolicy:
|
|
369
|
+
mandatory: true
|
|
370
|
+
reviewers: [tech-lead]
|
|
371
|
+
maxRounds: 3`)}
|
|
372
|
+
</div>
|
|
373
|
+
</div>
|
|
374
|
+
<div class="flex gap-4 items-start">
|
|
375
|
+
<div class="w-8 h-8 rounded-full bg-accent/20 text-accent-light flex items-center justify-center font-bold flex-shrink-0">3</div>
|
|
376
|
+
<div class="flex-1">
|
|
377
|
+
<div class="text-white font-medium">验证 & 部署</div>
|
|
378
|
+
${codeBlock(`# 验证格式
|
|
379
|
+
npx uni validate universe.yaml
|
|
380
|
+
|
|
381
|
+
# 预览部署(不实际写入文件)
|
|
382
|
+
npx uni deploy universe.yaml --dry-run
|
|
383
|
+
|
|
384
|
+
# 正式部署到 OpenClaw
|
|
385
|
+
npx uni deploy universe.yaml
|
|
386
|
+
# 输出:
|
|
387
|
+
# ✓ 生成 SOUL.md × 2
|
|
388
|
+
# ✓ 创建 workspace-tech-lead/, workspace-dev-alpha/
|
|
389
|
+
# ✓ 创建 agents/tech-lead/agent/, agents/dev-alpha/agent/
|
|
390
|
+
# ✓ 注册 2 个 Agent 到 openclaw.json
|
|
391
|
+
# ✓ 注册 Universe "my-team" 到 uni-registry.json`)}
|
|
392
|
+
</div>
|
|
393
|
+
</div>
|
|
394
|
+
<div class="flex gap-4 items-start">
|
|
395
|
+
<div class="w-8 h-8 rounded-full bg-accent/20 text-accent-light flex items-center justify-center font-bold flex-shrink-0">4</div>
|
|
396
|
+
<div class="flex-1">
|
|
397
|
+
<div class="text-white font-medium">启动 Dashboard</div>
|
|
398
|
+
${codeBlock(`# 启动 Web 仪表盘(默认端口 8089)
|
|
399
|
+
npx uni dashboard
|
|
400
|
+
|
|
401
|
+
# 或指定端口
|
|
402
|
+
npx uni dashboard --port 3000
|
|
403
|
+
|
|
404
|
+
# 浏览器打开 http://localhost:8089 即可看到首页`)}
|
|
405
|
+
</div>
|
|
406
|
+
</div>
|
|
407
|
+
<div class="flex gap-4 items-start">
|
|
408
|
+
<div class="w-8 h-8 rounded-full bg-accent/20 text-accent-light flex items-center justify-center font-bold flex-shrink-0">5</div>
|
|
409
|
+
<div class="flex-1">
|
|
410
|
+
<div class="text-white font-medium">验证部署结果</div>
|
|
411
|
+
${codeBlock(`# 用 OpenClaw CLI 查看已注册的 Agent
|
|
412
|
+
openclaw agents list
|
|
413
|
+
# 输出类似:
|
|
414
|
+
# tech-lead Technical Lead
|
|
415
|
+
# dev-alpha Software Engineer
|
|
416
|
+
|
|
417
|
+
# 查看生成的 SOUL.md
|
|
418
|
+
cat ~/.openclaw/workspace-tech-lead/SOUL.md
|
|
419
|
+
|
|
420
|
+
# 手动触发一次 Agent 执行
|
|
421
|
+
openclaw agent --agent tech-lead --message "请审查以下代码..."`)}
|
|
422
|
+
</div>
|
|
423
|
+
</div>
|
|
424
|
+
</div>
|
|
425
|
+
</div>
|
|
426
|
+
|
|
427
|
+
<!-- 4. universe.yaml -->
|
|
428
|
+
<div id="universe-yaml" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
429
|
+
<h2 class="text-xl font-semibold text-white mb-4">4. universe.yaml 完整语法</h2>
|
|
430
|
+
<div class="text-gray-300 text-sm space-y-4">
|
|
431
|
+
<p>universe.yaml 是整个系统的核心配置。以下是完整字段参考:</p>
|
|
432
|
+
|
|
433
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
434
|
+
<div class="text-white font-medium mb-2">顶层字段</div>
|
|
435
|
+
<table class="w-full text-xs">
|
|
436
|
+
<thead><tr class="text-gray-500"><th class="text-left py-1">字段</th><th class="text-left py-1">类型</th><th class="text-left py-1">必填</th><th class="text-left py-1">说明</th></tr></thead>
|
|
437
|
+
<tbody class="text-gray-400">
|
|
438
|
+
<tr><td class="py-1"><code class="text-accent-light">name</code></td><td>string</td><td>✓</td><td>Uni 唯一标识,如 "zhenhuan-palace"</td></tr>
|
|
439
|
+
<tr><td class="py-1"><code class="text-accent-light">type</code></td><td>string</td><td>✓</td><td>hierarchical / flat / competitive / hybrid</td></tr>
|
|
440
|
+
<tr><td class="py-1"><code class="text-accent-light">version</code></td><td>string</td><td></td><td>语义化版本,默认 "0.1.0"</td></tr>
|
|
441
|
+
<tr><td class="py-1"><code class="text-accent-light">description</code></td><td>string</td><td></td><td>Uni 描述</td></tr>
|
|
442
|
+
<tr><td class="py-1"><code class="text-accent-light">agents</code></td><td>array</td><td>✓</td><td>Agent 列表,至少 1 个</td></tr>
|
|
443
|
+
<tr><td class="py-1"><code class="text-accent-light">relationships</code></td><td>array</td><td></td><td>Agent 之间的关系</td></tr>
|
|
444
|
+
<tr><td class="py-1"><code class="text-accent-light">governance</code></td><td>object</td><td></td><td>治理规则(决策模型、权限、审批)</td></tr>
|
|
445
|
+
<tr><td class="py-1"><code class="text-accent-light">protocols</code></td><td>array</td><td></td><td>工作流状态机定义</td></tr>
|
|
446
|
+
<tr><td class="py-1"><code class="text-accent-light">resources</code></td><td>array</td><td></td><td>资源定义</td></tr>
|
|
447
|
+
<tr><td class="py-1"><code class="text-accent-light">evolution</code></td><td>object</td><td></td><td>演化/晋升/降级配置</td></tr>
|
|
448
|
+
<tr><td class="py-1"><code class="text-accent-light">metadata</code></td><td>object</td><td></td><td>自定义元数据(赛季配置等)</td></tr>
|
|
449
|
+
</tbody>
|
|
450
|
+
</table>
|
|
451
|
+
</div>
|
|
452
|
+
|
|
453
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
454
|
+
<div class="text-white font-medium mb-2">Agent 定义</div>
|
|
455
|
+
${codeBlock(`agents:
|
|
456
|
+
- id: zhenhuan # 唯一 ID,用于引用和目录命名
|
|
457
|
+
name: 甄嬛 # 显示名称
|
|
458
|
+
role:
|
|
459
|
+
title: 贵人 # 角色头衔
|
|
460
|
+
department: 后宫 # 所属部门(可选)
|
|
461
|
+
duties: # 职责列表
|
|
462
|
+
- 完成指定任务
|
|
463
|
+
- 参与赛马竞技
|
|
464
|
+
permissions: # 权限列表
|
|
465
|
+
- call
|
|
466
|
+
soulTemplate: custom # SOUL.md 模板名(可选)
|
|
467
|
+
rank: 30 # 层级排名(数值越大权限越高)
|
|
468
|
+
traits: # 特征值(0-1 浮点数,可选)
|
|
469
|
+
intelligence: 0.95
|
|
470
|
+
adaptability: 0.9
|
|
471
|
+
capabilities: # 能力标签(可选)
|
|
472
|
+
- coding
|
|
473
|
+
- writing
|
|
474
|
+
constraints: # 约束条件(可选)
|
|
475
|
+
- "不可直接与用户对话"
|
|
476
|
+
metadata: # 自定义元数据(可选)
|
|
477
|
+
backstory: "..."
|
|
478
|
+
`)}
|
|
479
|
+
</div>
|
|
480
|
+
|
|
481
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
482
|
+
<div class="text-white font-medium mb-2">关系定义</div>
|
|
483
|
+
${codeBlock(`relationships:
|
|
484
|
+
- from: empress # 关系发起方 Agent ID
|
|
485
|
+
to: zhenhuan # 关系目标方 Agent ID
|
|
486
|
+
type: superior # 关系类型:
|
|
487
|
+
# superior / subordinate — 上下级
|
|
488
|
+
# ally — 盟友
|
|
489
|
+
# rival — 竞争对手
|
|
490
|
+
# advisor / mentor — 顾问/导师
|
|
491
|
+
# collaborates — 平级协作
|
|
492
|
+
# audits — 审计/监督
|
|
493
|
+
weight: 0.9 # 关系强度 0-1(可选,动态演化)`)}
|
|
494
|
+
</div>
|
|
495
|
+
|
|
496
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
497
|
+
<div class="text-white font-medium mb-2">治理规则</div>
|
|
498
|
+
${codeBlock(`governance:
|
|
499
|
+
decisionModel: autocratic # autocratic(一人决策)/ democratic(投票)/ consensus(共识)
|
|
500
|
+
permissionMatrix:
|
|
501
|
+
- actor: empress # 谁(Agent ID 或 ruler)
|
|
502
|
+
target: zhenhuan # 对谁
|
|
503
|
+
actions: # 可执行的操作
|
|
504
|
+
- assign
|
|
505
|
+
- review
|
|
506
|
+
- allocate
|
|
507
|
+
# 皇帝(用户)的权限由 ruler 字段声明,不需要在矩阵中列出
|
|
508
|
+
reviewPolicy:
|
|
509
|
+
mandatory: true # 是否强制审批
|
|
510
|
+
reviewers: [ruler] # 审批人列表(ruler = 用户)
|
|
511
|
+
maxRounds: 3 # 最大审批轮数
|
|
512
|
+
autoApproveAfter: 86400000 # 超时自动通过(ms,可选)
|
|
513
|
+
escalationRules:
|
|
514
|
+
- trigger: "争端涉及三人以上"
|
|
515
|
+
escalateTo: ruler # 上报给用户
|
|
516
|
+
action: reassign`)}
|
|
517
|
+
</div>
|
|
518
|
+
|
|
519
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
520
|
+
<div class="text-white font-medium mb-2">资源定义</div>
|
|
521
|
+
${codeBlock(`resources:
|
|
522
|
+
- name: 圣宠 # 资源名称
|
|
523
|
+
type: finite # finite(有限)/ renewable(可再生)/ positional(位置性)
|
|
524
|
+
total: 1000 # 总量
|
|
525
|
+
distribution: competitive # equal / hierarchy / merit / competitive
|
|
526
|
+
decayRate: 0.05 # 衰减率 — 每周期减少 5%(可选)
|
|
527
|
+
refreshInterval: 2592000000 # 刷新间隔,ms(仅 renewable)
|
|
528
|
+
description: 核心影响力指标`)}
|
|
529
|
+
</div>
|
|
530
|
+
|
|
531
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
532
|
+
<div class="text-white font-medium mb-2">演化配置</div>
|
|
533
|
+
${codeBlock(`evolution:
|
|
534
|
+
performanceWindow: 50 # 评估窗口:最近 N 次表现
|
|
535
|
+
promotionThreshold: 75 # 晋升阈值(绩效分 0-100)
|
|
536
|
+
demotionThreshold: 30 # 降级阈值
|
|
537
|
+
memoryRetention: 1000 # 组织记忆保留条数
|
|
538
|
+
evolutionInterval: 604800000 # 演化周期(7 天,ms)`)}
|
|
539
|
+
</div>
|
|
540
|
+
</div>
|
|
541
|
+
</div>
|
|
542
|
+
|
|
543
|
+
<!-- 5. Uni Types -->
|
|
544
|
+
<div id="uni-types" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
545
|
+
<h2 class="text-xl font-semibold text-white mb-4">5. Uni 类型与组织模板</h2>
|
|
546
|
+
<div class="text-sm space-y-4">
|
|
547
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
548
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
549
|
+
<span class="badge bg-blue-500/20 text-blue-300 mb-2">hierarchical</span>
|
|
550
|
+
<p class="text-gray-400 mt-2"><strong class="text-white">层级制</strong> — 明确的上下级,如公司组织、政府部门、军队。决策自上而下。</p>
|
|
551
|
+
<p class="text-gray-500 mt-1 text-xs">模板:government, corporation, military</p>
|
|
552
|
+
</div>
|
|
553
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
554
|
+
<span class="badge bg-green-500/20 text-green-300 mb-2">flat</span>
|
|
555
|
+
<p class="text-gray-400 mt-2"><strong class="text-white">扁平制</strong> — 平等协作,民主投票决策。适合开源社区、合伙制。</p>
|
|
556
|
+
<p class="text-gray-500 mt-1 text-xs">模板:flat</p>
|
|
557
|
+
</div>
|
|
558
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
559
|
+
<span class="badge bg-red-500/20 text-red-300 mb-2">competitive</span>
|
|
560
|
+
<p class="text-gray-400 mt-2"><strong class="text-white">竞争制</strong> — ELO 排名、赛马淘汰。裁判 + 选手模式,绩效导向。</p>
|
|
561
|
+
<p class="text-gray-500 mt-1 text-xs">模板:competitive(如 zhenhuan-uni)</p>
|
|
562
|
+
</div>
|
|
563
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
564
|
+
<span class="badge bg-purple-500/20 text-purple-300 mb-2">hybrid</span>
|
|
565
|
+
<p class="text-gray-400 mt-2"><strong class="text-white">混合制</strong> — 多种模型组合。部分层级、部分竞争、部分协作。</p>
|
|
566
|
+
<p class="text-gray-500 mt-1 text-xs">默认类型,适合复杂组织</p>
|
|
567
|
+
</div>
|
|
568
|
+
</div>
|
|
569
|
+
<p class="text-gray-400">使用脚手架创建特定模板的项目:</p>
|
|
570
|
+
${codeBlock(`npx create-uni my-project --template competitive
|
|
571
|
+
npx create-uni my-team --template corporation
|
|
572
|
+
npx create-uni my-community --template flat`)}
|
|
573
|
+
</div>
|
|
574
|
+
</div>
|
|
575
|
+
|
|
576
|
+
<!-- 6. Deploy -->
|
|
577
|
+
<div id="deploy" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
578
|
+
<h2 class="text-xl font-semibold text-white mb-4">6. 部署到 OpenClaw</h2>
|
|
579
|
+
<div class="text-gray-300 text-sm space-y-4">
|
|
580
|
+
<p><code class="bg-surface px-1.5 py-0.5 rounded text-accent-light text-xs">uni deploy</code> 是核心命令,它完成以下全部操作:</p>
|
|
581
|
+
|
|
582
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
583
|
+
<div class="text-white font-medium mb-2">部署做了什么?</div>
|
|
584
|
+
<ol class="space-y-1 ml-4 text-gray-400 list-decimal list-inside">
|
|
585
|
+
<li>读取 <code class="text-accent-light">universe.yaml</code>,解析和验证</li>
|
|
586
|
+
<li>为每个 Agent 生成 <strong class="text-white">SOUL.md</strong>(人格定义文件)</li>
|
|
587
|
+
<li>创建 <strong class="text-white">workspace 目录</strong>:<code class="text-accent-light">~/.openclaw/workspace-{id}/</code></li>
|
|
588
|
+
<li>将 SOUL.md 写入对应的 workspace 目录</li>
|
|
589
|
+
<li>创建 <strong class="text-white">Agent 运行时目录</strong>:<code class="text-accent-light">~/.openclaw/agents/{id}/agent/</code> 和 <code class="text-accent-light">agents/{id}/sessions/</code></li>
|
|
590
|
+
<li>将 Agent 注册到 <code class="text-accent-light">~/.openclaw/openclaw.json</code>(含 workspace + agentDir 字段)</li>
|
|
591
|
+
<li>将 Universe 注册到 <code class="text-accent-light">~/.openclaw/uni-registry.json</code></li>
|
|
592
|
+
<li>生成 <strong class="text-white">权限矩阵参考文件</strong>:<code class="text-accent-light">~/.openclaw/{name}-permissions.md</code></li>
|
|
593
|
+
</ol>
|
|
594
|
+
</div>
|
|
595
|
+
|
|
596
|
+
${codeBlock(`# 基本部署
|
|
597
|
+
npx uni deploy universe.yaml
|
|
598
|
+
|
|
599
|
+
# 指定 OpenClaw 目录(默认 ~/.openclaw)
|
|
600
|
+
npx uni deploy universe.yaml --dir /path/to/openclaw
|
|
601
|
+
|
|
602
|
+
# 指定 SOUL.md 语言(zh 中文 / en 英文)
|
|
603
|
+
npx uni deploy universe.yaml --lang zh
|
|
604
|
+
|
|
605
|
+
# 预览模式 — 显示将要做什么但不实际执行
|
|
606
|
+
npx uni deploy universe.yaml --dry-run`)}
|
|
607
|
+
|
|
608
|
+
<div class="bg-yellow-900/20 border border-yellow-700/30 rounded-lg p-4">
|
|
609
|
+
<div class="text-yellow-300 font-medium mb-1">⚠️ 注意</div>
|
|
610
|
+
<ul class="text-yellow-200/70 space-y-1 text-xs">
|
|
611
|
+
<li>• 重复部署是安全的 — 已注册的 Agent 不会重复添加到 openclaw.json</li>
|
|
612
|
+
<li>• 但 SOUL.md 会被覆盖。如果你手动编辑过 SOUL.md,部署前请备份</li>
|
|
613
|
+
<li>• 部署前确保 OpenClaw 已安装且 <code>~/.openclaw/</code> 目录存在</li>
|
|
614
|
+
</ul>
|
|
615
|
+
</div>
|
|
616
|
+
</div>
|
|
617
|
+
</div>
|
|
618
|
+
|
|
619
|
+
<!-- 7. OpenClaw -->
|
|
620
|
+
<div id="openclaw" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
621
|
+
<h2 class="text-xl font-semibold text-white mb-4">7. OpenClaw 使用指南</h2>
|
|
622
|
+
<div class="text-gray-300 text-sm space-y-4">
|
|
623
|
+
<p>OpenClaw 是 Agent 的运行时环境。Agent 在 OpenClaw 中被执行,Uni 系统通过文件协议与 OpenClaw 交互。</p>
|
|
624
|
+
|
|
625
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
626
|
+
<div class="text-white font-medium mb-2">OpenClaw 核心概念</div>
|
|
627
|
+
<ul class="space-y-2 ml-4 text-gray-400">
|
|
628
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> <strong class="text-white">Agent</strong> — 一个独立的 AI 实体,有自己的 workspace 和会话历史</li>
|
|
629
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> <strong class="text-white">Gateway</strong> — WebSocket 网关,管理所有 Agent 的执行(默认端口 18789)</li>
|
|
630
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> <strong class="text-white">Workspace</strong> — Agent 的工作目录,包含 SOUL.md、TASK.md、SUBMISSION.md 等文件</li>
|
|
631
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> <strong class="text-white">Session</strong> — 一次 Agent 执行会话,保存在 agents/{id}/sessions/ 下</li>
|
|
632
|
+
</ul>
|
|
633
|
+
</div>
|
|
634
|
+
|
|
635
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
636
|
+
<div class="text-white font-medium mb-2">常用 OpenClaw 命令</div>
|
|
637
|
+
${codeBlock(`# 首次配置(设置 API Key、默认模型等)
|
|
638
|
+
openclaw config
|
|
639
|
+
|
|
640
|
+
# 查看所有已注册的 Agent
|
|
641
|
+
openclaw agents list
|
|
642
|
+
|
|
643
|
+
# 添加新 Agent(uni deploy 会自动完成,但也可手动)
|
|
644
|
+
openclaw agents add --id my-agent --name "我的Agent"
|
|
645
|
+
|
|
646
|
+
# 直接与某个 Agent 对话
|
|
647
|
+
openclaw agent --agent zhenhuan --message "请完成以下任务..."
|
|
648
|
+
|
|
649
|
+
# 启动 Gateway(前台运行)
|
|
650
|
+
openclaw gateway run
|
|
651
|
+
|
|
652
|
+
# 启动 Gateway(作为系统服务,后台运行)
|
|
653
|
+
openclaw gateway start
|
|
654
|
+
|
|
655
|
+
# 查看 Gateway 状态
|
|
656
|
+
openclaw gateway status
|
|
657
|
+
|
|
658
|
+
# 检查系统健康
|
|
659
|
+
openclaw doctor
|
|
660
|
+
|
|
661
|
+
# 查看日志
|
|
662
|
+
openclaw logs --tail 50`)}
|
|
663
|
+
</div>
|
|
664
|
+
|
|
665
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
666
|
+
<div class="text-white font-medium mb-2">openclaw.json 配置结构</div>
|
|
667
|
+
<p class="text-gray-400 mb-2">部署后,<code class="text-accent-light">~/.openclaw/openclaw.json</code> 中的 agents 列表格式:</p>
|
|
668
|
+
${codeBlock(`{
|
|
669
|
+
"agents": {
|
|
670
|
+
"defaults": {
|
|
671
|
+
"workspace": "~/.openclaw/workspace",
|
|
672
|
+
"maxConcurrent": 4
|
|
673
|
+
},
|
|
674
|
+
"list": [
|
|
675
|
+
{
|
|
676
|
+
"id": "empress",
|
|
677
|
+
"name": "皇后",
|
|
678
|
+
"workspace": "~/.openclaw/workspace-empress",
|
|
679
|
+
"agentDir": "~/.openclaw/agents/empress/agent"
|
|
680
|
+
},
|
|
681
|
+
{
|
|
682
|
+
"id": "zhenhuan",
|
|
683
|
+
"name": "甄嬛",
|
|
684
|
+
"workspace": "~/.openclaw/workspace-zhenhuan",
|
|
685
|
+
"agentDir": "~/.openclaw/agents/zhenhuan/agent"
|
|
686
|
+
}
|
|
687
|
+
]
|
|
688
|
+
},
|
|
689
|
+
"gateway": {
|
|
690
|
+
"port": 18789,
|
|
691
|
+
"mode": "local"
|
|
692
|
+
}
|
|
693
|
+
}`)}
|
|
694
|
+
</div>
|
|
695
|
+
</div>
|
|
696
|
+
</div>
|
|
697
|
+
|
|
698
|
+
<!-- 8. File Protocol -->
|
|
699
|
+
<div id="file-protocol" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
700
|
+
<h2 class="text-xl font-semibold text-white mb-4">8. 文件协议详解</h2>
|
|
701
|
+
<div class="text-gray-300 text-sm space-y-4">
|
|
702
|
+
<p>Uni 系统通过在 OpenClaw workspace 中读写 Markdown 文件与 Agent 通信。这是一种<strong class="text-white">零耦合</strong>的集成方式 — Agent 不需要实现任何 HTTP 接口。</p>
|
|
703
|
+
|
|
704
|
+
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
705
|
+
<div class="bg-surface rounded-lg p-4 border border-green-700/30">
|
|
706
|
+
<div class="text-green-400 font-mono font-medium mb-2">SOUL.md</div>
|
|
707
|
+
<div class="text-xs text-gray-500 mb-2">写入时机:<code>uni deploy</code> 部署时</div>
|
|
708
|
+
<p class="text-gray-400">Agent 的人格定义 — 身份、职责、性格、评判标准。相当于 Agent 的"宪法"。</p>
|
|
709
|
+
<div class="mt-2 text-xs text-gray-500">路径:<code>~/.openclaw/workspace-{id}/SOUL.md</code></div>
|
|
710
|
+
</div>
|
|
711
|
+
<div class="bg-surface rounded-lg p-4 border border-yellow-700/30">
|
|
712
|
+
<div class="text-yellow-400 font-mono font-medium mb-2">TASK.md</div>
|
|
713
|
+
<div class="text-xs text-gray-500 mb-2">写入时机:每次任务调度时</div>
|
|
714
|
+
<p class="text-gray-400">当前任务描述 — 标题、要求、评判标准、时间限制。由 TaskDispatcher 写入,Agent 读取并执行。</p>
|
|
715
|
+
<div class="mt-2 text-xs text-gray-500">路径:<code>~/.openclaw/workspace-{id}/TASK.md</code></div>
|
|
716
|
+
</div>
|
|
717
|
+
<div class="bg-surface rounded-lg p-4 border border-blue-700/30">
|
|
718
|
+
<div class="text-blue-400 font-mono font-medium mb-2">SUBMISSION.md</div>
|
|
719
|
+
<div class="text-xs text-gray-500 mb-2">写入时机:Agent 完成任务后</div>
|
|
720
|
+
<p class="text-gray-400">Agent 的产出 — 任务执行结果。Agent 自行写入,TaskDispatcher 轮询收集(默认每 2 秒检查一次)。</p>
|
|
721
|
+
<div class="mt-2 text-xs text-gray-500">路径:<code>~/.openclaw/workspace-{id}/SUBMISSION.md</code></div>
|
|
722
|
+
</div>
|
|
723
|
+
</div>
|
|
724
|
+
|
|
725
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
726
|
+
<div class="text-white font-medium mb-2">完整调度流程</div>
|
|
727
|
+
${codeBlock(`1. Uni 系统调用 dispatchAndRace()
|
|
728
|
+
2. TaskDispatcher 为每个参赛 Agent 写入 TASK.md
|
|
729
|
+
3. OpenClaw 检测到 TASK.md 变化,触发 Agent 执行
|
|
730
|
+
4. Agent 读取 SOUL.md(人格)+ TASK.md(任务)
|
|
731
|
+
5. Agent 调用 Claude API 生成回答
|
|
732
|
+
6. Agent 将结果写入 SUBMISSION.md
|
|
733
|
+
7. TaskDispatcher 每 2s 轮询 SUBMISSION.md
|
|
734
|
+
8. 收集到所有提交(或超时),进入评审
|
|
735
|
+
9. 评审完成,更新 ELO,清理 TASK.md / SUBMISSION.md`)}
|
|
736
|
+
</div>
|
|
737
|
+
|
|
738
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
739
|
+
<div class="text-white font-medium mb-2">SOUL.md 示例</div>
|
|
740
|
+
${codeBlock(`# 甄嬛 - 贵人
|
|
741
|
+
|
|
742
|
+
## 身份
|
|
743
|
+
你是后宫赛马体系中的参赛者——甄嬛。你需要在竞争中展现最佳表现。
|
|
744
|
+
|
|
745
|
+
## 核心职责
|
|
746
|
+
1. **完成指定任务** — 在赛马竞技中提交高质量的输出
|
|
747
|
+
2. **参与赛马竞技** — 与其他嫔妃公平竞争
|
|
748
|
+
3. **经营人际关系** — 寻找盟友,应对竞争对手
|
|
749
|
+
|
|
750
|
+
## 性格特质
|
|
751
|
+
- 智慧:善于从全局思考,找到最优策略
|
|
752
|
+
- 适应性:面对不同类型的任务都能灵活应对
|
|
753
|
+
- 坚韧:即使遇到挫折也不轻言放弃
|
|
754
|
+
|
|
755
|
+
## 行为准则
|
|
756
|
+
- 输出质量第一,速度第二
|
|
757
|
+
- 善用策略,但不损害他人
|
|
758
|
+
- 保持优雅,展现实力`)}
|
|
759
|
+
</div>
|
|
760
|
+
</div>
|
|
761
|
+
</div>
|
|
762
|
+
|
|
763
|
+
<!-- 9. Directory Structure -->
|
|
764
|
+
<div id="directory" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
765
|
+
<h2 class="text-xl font-semibold text-white mb-4">9. 目录结构一览</h2>
|
|
766
|
+
<div class="text-gray-300 text-sm">
|
|
767
|
+
${codeBlock(`~/.openclaw/ # OpenClaw 根目录
|
|
768
|
+
├── openclaw.json # 主配置(Agent 列表、Gateway、认证)
|
|
769
|
+
├── uni-registry.json # Uni 注册中心(跟踪所有已部署的 Universe)
|
|
770
|
+
├── zhenhuan-palace-permissions.md # 权限矩阵参考(部署时自动生成)
|
|
771
|
+
│
|
|
772
|
+
├── agents/ # Agent 运行时目录(仅嫔妃,皇帝是用户)
|
|
773
|
+
│ ├── empress/
|
|
774
|
+
│ │ ├── agent/ # 运行时配置
|
|
775
|
+
│ │ └── sessions/ # 会话历史(每次执行的记录)
|
|
776
|
+
│ ├── zhenhuan/
|
|
777
|
+
│ │ ├── agent/
|
|
778
|
+
│ │ └── sessions/
|
|
779
|
+
│ └── ...
|
|
780
|
+
│
|
|
781
|
+
├── workspace/ # 默认 workspace(OpenClaw 自带的 main agent)
|
|
782
|
+
│ ├── SOUL.md
|
|
783
|
+
│ ├── IDENTITY.md # Agent 身份标识
|
|
784
|
+
│ ├── HEARTBEAT.md # 心跳状态
|
|
785
|
+
│ ├── USER.md # 用户上下文
|
|
786
|
+
│ ├── TOOLS.md # 可用工具
|
|
787
|
+
│ └── memory/ # 会话记忆
|
|
788
|
+
│
|
|
789
|
+
├── workspace-empress/ # 皇后 Agent 的 workspace
|
|
790
|
+
│ ├── SOUL.md # ← uni deploy 生成
|
|
791
|
+
│ ├── TASK.md # ← TaskDispatcher 写入(运行时)
|
|
792
|
+
│ └── SUBMISSION.md # ← Agent 写入(运行时)
|
|
793
|
+
│
|
|
794
|
+
├── workspace-zhenhuan/ # 甄嬛 Agent 的 workspace
|
|
795
|
+
│ ├── SOUL.md
|
|
796
|
+
│ ├── TASK.md
|
|
797
|
+
│ └── SUBMISSION.md
|
|
798
|
+
│
|
|
799
|
+
├── credentials/ # API 密钥存储
|
|
800
|
+
├── identity/ # 身份配置
|
|
801
|
+
├── logs/ # Gateway 日志
|
|
802
|
+
├── memory/ # 全局记忆
|
|
803
|
+
├── skills/ # 已安装的技能
|
|
804
|
+
└── cron/ # 定时任务`)}
|
|
805
|
+
</div>
|
|
806
|
+
</div>
|
|
807
|
+
|
|
808
|
+
<!-- 10. Uni CLI -->
|
|
809
|
+
<div id="cli-uni" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
810
|
+
<h2 class="text-xl font-semibold text-white mb-4">10. Uni CLI 命令参考</h2>
|
|
811
|
+
<div class="text-sm space-y-3">
|
|
812
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30">
|
|
813
|
+
<code class="text-accent-light">uni deploy <file></code>
|
|
814
|
+
<span class="text-gray-400 ml-3">部署 universe.yaml 到 OpenClaw</span>
|
|
815
|
+
<div class="text-gray-500 text-xs mt-1">选项:<code>--dir</code> 指定目录, <code>--dry-run</code> 预览, <code>--lang zh|en</code> SOUL.md 语言</div>
|
|
816
|
+
</div>
|
|
817
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30">
|
|
818
|
+
<code class="text-accent-light">uni validate <file></code>
|
|
819
|
+
<span class="text-gray-400 ml-3">验证 universe.yaml 格式 — 检查 Schema + 语义(引用的 Agent 是否存在等)</span>
|
|
820
|
+
</div>
|
|
821
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30">
|
|
822
|
+
<code class="text-accent-light">uni visualize <file></code>
|
|
823
|
+
<span class="text-gray-400 ml-3">在终端生成 ASCII 关系图</span>
|
|
824
|
+
</div>
|
|
825
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30">
|
|
826
|
+
<code class="text-accent-light">uni inspect <file> [--agent <id>]</code>
|
|
827
|
+
<span class="text-gray-400 ml-3">详细检视 — 不加 --agent 显示全局概览,加则显示单个 Agent 详情</span>
|
|
828
|
+
</div>
|
|
829
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30">
|
|
830
|
+
<code class="text-accent-light">uni init [name]</code>
|
|
831
|
+
<span class="text-gray-400 ml-3">交互式初始化新 Uni 项目(生成 universe.yaml 模板 + package.json)</span>
|
|
832
|
+
</div>
|
|
833
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30">
|
|
834
|
+
<code class="text-accent-light">uni dashboard [--port 8089]</code>
|
|
835
|
+
<span class="text-gray-400 ml-3">启动 Web 仪表盘(当前页面就是 Dashboard)</span>
|
|
836
|
+
</div>
|
|
837
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30">
|
|
838
|
+
<code class="text-accent-light">uni list</code>
|
|
839
|
+
<span class="text-gray-400 ml-3">列出所有已注册的 Uni(读取 uni-registry.json)</span>
|
|
840
|
+
</div>
|
|
841
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30">
|
|
842
|
+
<code class="text-accent-light">uni status</code>
|
|
843
|
+
<span class="text-gray-400 ml-3">部署概览 — 显示每个 Uni 的 Agent 数量、类型、版本</span>
|
|
844
|
+
</div>
|
|
845
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30">
|
|
846
|
+
<code class="text-accent-light">uni reset <id></code>
|
|
847
|
+
<span class="text-gray-400 ml-3">重置运行时数据(清除 sessions/TASK.md/SUBMISSION.md,保留 SOUL.md 和配置)</span>
|
|
848
|
+
</div>
|
|
849
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30">
|
|
850
|
+
<code class="text-accent-light">uni cleanup <id></code>
|
|
851
|
+
<span class="text-gray-400 ml-3">彻底删除 Uni — workspace 目录 + agent 目录 + openclaw.json 条目 + 注册表条目</span>
|
|
852
|
+
</div>
|
|
853
|
+
</div>
|
|
854
|
+
</div>
|
|
855
|
+
|
|
856
|
+
<!-- 11. OpenClaw CLI -->
|
|
857
|
+
<div id="cli-openclaw" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
858
|
+
<h2 class="text-xl font-semibold text-white mb-4">11. OpenClaw CLI 命令参考</h2>
|
|
859
|
+
<div class="text-gray-300 text-sm space-y-4">
|
|
860
|
+
<p>以下是部署和运行 Agent 时最常用的 OpenClaw 命令:</p>
|
|
861
|
+
|
|
862
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
863
|
+
<div class="text-white font-medium mb-2">Agent 管理</div>
|
|
864
|
+
${codeBlock(`openclaw agents list # 列出所有已注册的 Agent
|
|
865
|
+
openclaw agents add # 交互式添加新 Agent
|
|
866
|
+
openclaw agents delete # 删除 Agent 及其 workspace
|
|
867
|
+
openclaw agents set-identity # 修改 Agent 名称/图标`)}
|
|
868
|
+
</div>
|
|
869
|
+
|
|
870
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
871
|
+
<div class="text-white font-medium mb-2">执行 Agent</div>
|
|
872
|
+
${codeBlock(`# 向指定 Agent 发送消息并执行
|
|
873
|
+
openclaw agent --agent zhenhuan --message "评审以下代码..."
|
|
874
|
+
|
|
875
|
+
# JSON 输出模式
|
|
876
|
+
openclaw agent --agent zhenhuan --message "写一首诗" --json
|
|
877
|
+
|
|
878
|
+
# 设置超时
|
|
879
|
+
openclaw agent --agent zhenhuan --message "..." --timeout 120`)}
|
|
880
|
+
</div>
|
|
881
|
+
|
|
882
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
883
|
+
<div class="text-white font-medium mb-2">Gateway 管理</div>
|
|
884
|
+
${codeBlock(`openclaw gateway run # 前台运行 Gateway
|
|
885
|
+
openclaw gateway start # 作为系统服务后台运行
|
|
886
|
+
openclaw gateway status # 查看服务状态
|
|
887
|
+
openclaw gateway health # 健康检查`)}
|
|
888
|
+
</div>
|
|
889
|
+
|
|
890
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
891
|
+
<div class="text-white font-medium mb-2">诊断与配置</div>
|
|
892
|
+
${codeBlock(`openclaw config # 交互式配置向导
|
|
893
|
+
openclaw config validate # 验证当前配置
|
|
894
|
+
openclaw doctor # 全面健康检查 + 自动修复
|
|
895
|
+
openclaw logs --tail 50 # 查看最近日志`)}
|
|
896
|
+
</div>
|
|
897
|
+
</div>
|
|
898
|
+
</div>
|
|
899
|
+
|
|
900
|
+
<!-- 12. API Reference -->
|
|
901
|
+
<div id="api-ref" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
902
|
+
<h2 class="text-xl font-semibold text-white mb-4">12. Dashboard REST API</h2>
|
|
903
|
+
<div class="text-sm space-y-2">
|
|
904
|
+
<p class="text-gray-400 mb-3">Dashboard 提供 JSON API,可用 curl 或任何 HTTP 客户端调用:</p>
|
|
905
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30 flex gap-3 items-center">
|
|
906
|
+
<span class="badge bg-green-500/20 text-green-300 w-14 justify-center">GET</span>
|
|
907
|
+
<code class="text-gray-300">/api/unis</code>
|
|
908
|
+
<span class="text-gray-500 ml-auto">所有 Uni 列表</span>
|
|
909
|
+
</div>
|
|
910
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30 flex gap-3 items-center">
|
|
911
|
+
<span class="badge bg-green-500/20 text-green-300 w-14 justify-center">GET</span>
|
|
912
|
+
<code class="text-gray-300">/api/unis/:id</code>
|
|
913
|
+
<span class="text-gray-500 ml-auto">Uni 详情(Agent 列表 + 配置)</span>
|
|
914
|
+
</div>
|
|
915
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30 flex gap-3 items-center">
|
|
916
|
+
<span class="badge bg-green-500/20 text-green-300 w-14 justify-center">GET</span>
|
|
917
|
+
<code class="text-gray-300">/api/unis/:id/agents/:agentId</code>
|
|
918
|
+
<span class="text-gray-500 ml-auto">单个 Agent 详情 + workspace 状态</span>
|
|
919
|
+
</div>
|
|
920
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30 flex gap-3 items-center">
|
|
921
|
+
<span class="badge bg-green-500/20 text-green-300 w-14 justify-center">GET</span>
|
|
922
|
+
<code class="text-gray-300">/api/unis/:id/relationships</code>
|
|
923
|
+
<span class="text-gray-500 ml-auto">关系图(nodes + edges 格式)</span>
|
|
924
|
+
</div>
|
|
925
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30 flex gap-3 items-center">
|
|
926
|
+
<span class="badge bg-yellow-500/20 text-yellow-300 w-14 justify-center">POST</span>
|
|
927
|
+
<code class="text-gray-300">/api/unis/:id/reset</code>
|
|
928
|
+
<span class="text-gray-500 ml-auto">重置 Uni 运行时</span>
|
|
929
|
+
</div>
|
|
930
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30 flex gap-3 items-center">
|
|
931
|
+
<span class="badge bg-red-500/20 text-red-300 w-14 justify-center">POST</span>
|
|
932
|
+
<code class="text-gray-300">/api/unis/:id/cleanup</code>
|
|
933
|
+
<span class="text-gray-500 ml-auto">彻底删除 Uni</span>
|
|
934
|
+
</div>
|
|
935
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30 flex gap-3 items-center">
|
|
936
|
+
<span class="badge bg-green-500/20 text-green-300 w-14 justify-center">GET</span>
|
|
937
|
+
<code class="text-gray-300">/api/health</code>
|
|
938
|
+
<span class="text-gray-500 ml-auto">健康检查</span>
|
|
939
|
+
</div>
|
|
940
|
+
<div class="mt-4">
|
|
941
|
+
<div class="text-white font-medium mb-2">调用示例</div>
|
|
942
|
+
${codeBlock(`# 列出所有 Uni
|
|
943
|
+
curl http://localhost:8089/api/unis | jq
|
|
944
|
+
|
|
945
|
+
# 查看某个 Uni 详情
|
|
946
|
+
curl http://localhost:8089/api/unis/zhenhuan-palace | jq
|
|
947
|
+
|
|
948
|
+
# 重置(清除运行时数据)
|
|
949
|
+
curl -X POST http://localhost:8089/api/unis/zhenhuan-palace/reset
|
|
950
|
+
|
|
951
|
+
# 健康检查
|
|
952
|
+
curl http://localhost:8089/api/health | jq`)}
|
|
953
|
+
</div>
|
|
954
|
+
</div>
|
|
955
|
+
</div>
|
|
956
|
+
|
|
957
|
+
<!-- 13. Multi-Uni -->
|
|
958
|
+
<div id="multi-uni" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
959
|
+
<h2 class="text-xl font-semibold text-white mb-4">13. 多 Uni 管理</h2>
|
|
960
|
+
<div class="text-gray-300 text-sm space-y-3">
|
|
961
|
+
<p>系统支持同时部署多个 Uni,每个 Uni 独立管理。所有信息存储在 <code class="bg-surface px-1.5 py-0.5 rounded text-accent-light text-xs">~/.openclaw/uni-registry.json</code>。</p>
|
|
962
|
+
|
|
963
|
+
<div class="bg-surface rounded-lg p-4 border border-gray-700/30">
|
|
964
|
+
<div class="text-white font-medium mb-2">uni-registry.json 格式</div>
|
|
965
|
+
${codeBlock(`{
|
|
966
|
+
"version": "1.0.0",
|
|
967
|
+
"unis": [
|
|
968
|
+
{
|
|
969
|
+
"id": "zhenhuan-palace",
|
|
970
|
+
"description": "以甄嬛传后宫为背景的 Agent 竞争体系...",
|
|
971
|
+
"specPath": "/path/to/zhenhuan-uni/universe.yaml",
|
|
972
|
+
"type": "competitive",
|
|
973
|
+
"agentIds": ["empress", "zhenhuan", "huafei", ...],
|
|
974
|
+
"deployedAt": "2026-03-14T00:19:27.033Z",
|
|
975
|
+
"updatedAt": "2026-03-14T01:36:00.378Z",
|
|
976
|
+
"version": "0.1.0"
|
|
977
|
+
},
|
|
978
|
+
{
|
|
979
|
+
"id": "my-team",
|
|
980
|
+
"type": "corporation",
|
|
981
|
+
...
|
|
982
|
+
}
|
|
983
|
+
]
|
|
984
|
+
}`)}
|
|
985
|
+
</div>
|
|
986
|
+
|
|
987
|
+
<ul class="space-y-2 ml-4">
|
|
988
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> 每个 Uni 的 Agent 拥有独立的 workspace 和 agent 目录,互不冲突</li>
|
|
989
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> 在 <a href="/" class="text-accent-light hover:underline">首页</a> 可以看到所有已部署 Uni 的卡片概览</li>
|
|
990
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> 在 <a href="/manage" class="text-accent-light hover:underline">管理中心</a> 可以对每个 Uni 执行重置/清理操作</li>
|
|
991
|
+
<li class="flex gap-2"><span class="text-accent-light">•</span> 点击任意 Uni 卡片可查看详情页 — Agent 列表、关系图谱、workspace 状态</li>
|
|
992
|
+
</ul>
|
|
993
|
+
</div>
|
|
994
|
+
</div>
|
|
995
|
+
|
|
996
|
+
<!-- 14. Lifecycle -->
|
|
997
|
+
<div id="lifecycle" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
998
|
+
<h2 class="text-xl font-semibold text-white mb-4">14. 生命周期:重置 vs 清理 vs 更新</h2>
|
|
999
|
+
<div class="text-sm">
|
|
1000
|
+
<table class="w-full mb-4">
|
|
1001
|
+
<thead>
|
|
1002
|
+
<tr class="text-gray-500 text-left border-b border-gray-700/50">
|
|
1003
|
+
<th class="py-2 font-medium">操作</th>
|
|
1004
|
+
<th class="py-2 font-medium">命令</th>
|
|
1005
|
+
<th class="py-2 font-medium">做了什么</th>
|
|
1006
|
+
<th class="py-2 font-medium">保留什么</th>
|
|
1007
|
+
</tr>
|
|
1008
|
+
</thead>
|
|
1009
|
+
<tbody class="text-gray-400">
|
|
1010
|
+
<tr class="border-b border-gray-700/30">
|
|
1011
|
+
<td class="py-3"><span class="text-yellow-400">🔄 重置</span></td>
|
|
1012
|
+
<td class="py-3"><code class="text-accent-light">uni reset <id></code></td>
|
|
1013
|
+
<td class="py-3">删除 sessions/、TASK.md、SUBMISSION.md</td>
|
|
1014
|
+
<td class="py-3">SOUL.md、openclaw.json 条目、注册信息</td>
|
|
1015
|
+
</tr>
|
|
1016
|
+
<tr class="border-b border-gray-700/30">
|
|
1017
|
+
<td class="py-3"><span class="text-red-400">🗑️ 清理</span></td>
|
|
1018
|
+
<td class="py-3"><code class="text-accent-light">uni cleanup <id></code></td>
|
|
1019
|
+
<td class="py-3">删除全部:workspace/、agents/、openclaw.json 条目、注册信息</td>
|
|
1020
|
+
<td class="py-3">无 — 完全清除,如同从未部署过</td>
|
|
1021
|
+
</tr>
|
|
1022
|
+
<tr class="border-b border-gray-700/30">
|
|
1023
|
+
<td class="py-3"><span class="text-green-400">🔃 更新</span></td>
|
|
1024
|
+
<td class="py-3"><code class="text-accent-light">uni deploy</code>(重新执行)</td>
|
|
1025
|
+
<td class="py-3">重新生成 SOUL.md,新增 Agent 自动注册</td>
|
|
1026
|
+
<td class="py-3">已有 Agent 的 openclaw.json 条目不会重复添加</td>
|
|
1027
|
+
</tr>
|
|
1028
|
+
</tbody>
|
|
1029
|
+
</table>
|
|
1030
|
+
<div class="bg-yellow-900/20 border border-yellow-700/30 rounded-lg p-3">
|
|
1031
|
+
<p class="text-yellow-200/70 text-xs"><strong class="text-yellow-300">使用场景:</strong>如果 Agent 的会话数据或提交结果变得混乱,使用<strong>重置</strong>。如果要完全卸载一个 Uni,使用<strong>清理</strong>。如果修改了 universe.yaml(增减 Agent 或改角色),重新执行<strong>部署</strong>即可。</p>
|
|
1032
|
+
</div>
|
|
1033
|
+
</div>
|
|
1034
|
+
</div>
|
|
1035
|
+
|
|
1036
|
+
<!-- 15. Extension -->
|
|
1037
|
+
<div id="extension" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
1038
|
+
<h2 class="text-xl font-semibold text-white mb-4">15. Dashboard 扩展机制</h2>
|
|
1039
|
+
<div class="text-gray-300 text-sm space-y-3">
|
|
1040
|
+
<p>特定的 Uni 实例可以通过 <code class="text-accent-light">DashboardExtension</code> 接口向核心 Dashboard 注入自定义 API 路由和首页面板:</p>
|
|
1041
|
+
${codeBlock(`import { Hono } from 'hono';
|
|
1042
|
+
import { startDashboard } from '@agents-uni/core';
|
|
1043
|
+
import type { DashboardExtension, PanelDefinition } from '@agents-uni/core';
|
|
1044
|
+
|
|
1045
|
+
// 创建扩展路由
|
|
1046
|
+
const extRoutes = new Hono();
|
|
1047
|
+
extRoutes.get('/leaderboard', (c) => c.json(getLeaderboard()));
|
|
1048
|
+
extRoutes.get('/factions', (c) => c.json(getFactions()));
|
|
1049
|
+
|
|
1050
|
+
// 定义首页面板
|
|
1051
|
+
const panels: PanelDefinition[] = [
|
|
1052
|
+
{
|
|
1053
|
+
title: 'ELO 排行榜',
|
|
1054
|
+
renderHtml: () => '<div>...排行榜 HTML...</div>',
|
|
1055
|
+
},
|
|
1056
|
+
];
|
|
1057
|
+
|
|
1058
|
+
// 组装扩展
|
|
1059
|
+
const extension: DashboardExtension = {
|
|
1060
|
+
uniId: 'my-uni', // 扩展所属的 Uni ID
|
|
1061
|
+
routes: extRoutes, // Hono 路由实例,挂载到 /ext/my-uni/
|
|
1062
|
+
panels, // 首页面板(可选)
|
|
1063
|
+
};
|
|
1064
|
+
|
|
1065
|
+
// 启动 Dashboard 并加载扩展
|
|
1066
|
+
await startDashboard({
|
|
1067
|
+
port: 8089,
|
|
1068
|
+
extensions: [extension],
|
|
1069
|
+
});
|
|
1070
|
+
// 扩展 API 路径:GET /ext/my-uni/leaderboard
|
|
1071
|
+
// 扩展面板会自动显示在首页的「实时数据面板」区域`)}
|
|
1072
|
+
</div>
|
|
1073
|
+
</div>
|
|
1074
|
+
|
|
1075
|
+
<!-- 16. Troubleshooting -->
|
|
1076
|
+
<div id="troubleshooting" class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
1077
|
+
<h2 class="text-xl font-semibold text-white mb-4">16. 常见问题排查</h2>
|
|
1078
|
+
<div class="text-sm space-y-4">
|
|
1079
|
+
|
|
1080
|
+
<div class="bg-surface rounded-lg p-4 border border-red-700/20">
|
|
1081
|
+
<div class="text-red-300 font-medium mb-2">❌ <code>uni deploy</code> 报错 "找不到 universe.yaml"</div>
|
|
1082
|
+
<p class="text-gray-400">确认文件路径正确。deploy 命令需要完整路径或相对路径:</p>
|
|
1083
|
+
${codeBlock(`# 正确
|
|
1084
|
+
npx uni deploy ./universe.yaml
|
|
1085
|
+
npx uni deploy /absolute/path/universe.yaml
|
|
1086
|
+
|
|
1087
|
+
# 错误 — 文件名拼写
|
|
1088
|
+
npx uni deploy universe.yml # 应为 .yaml`)}
|
|
1089
|
+
</div>
|
|
1090
|
+
|
|
1091
|
+
<div class="bg-surface rounded-lg p-4 border border-red-700/20">
|
|
1092
|
+
<div class="text-red-300 font-medium mb-2">❌ 部署后 <code>openclaw agents list</code> 看不到 Agent</div>
|
|
1093
|
+
<p class="text-gray-400">检查 <code>~/.openclaw/openclaw.json</code> 中的 <code>agents.list</code> 是否包含你的 Agent。如果没有:</p>
|
|
1094
|
+
<ul class="text-gray-400 mt-1 ml-4 space-y-1">
|
|
1095
|
+
<li>• 确认部署时没有用 <code>--dry-run</code></li>
|
|
1096
|
+
<li>• 确认 <code>~/.openclaw/</code> 目录存在且有写权限</li>
|
|
1097
|
+
<li>• 尝试重新部署:<code>npx uni deploy universe.yaml</code></li>
|
|
1098
|
+
</ul>
|
|
1099
|
+
</div>
|
|
1100
|
+
|
|
1101
|
+
<div class="bg-surface rounded-lg p-4 border border-red-700/20">
|
|
1102
|
+
<div class="text-red-300 font-medium mb-2">❌ Dashboard 首页显示 "尚无已部署的 Uni"</div>
|
|
1103
|
+
<p class="text-gray-400">检查 <code>~/.openclaw/uni-registry.json</code> 是否存在且包含你的 Uni。可能原因:</p>
|
|
1104
|
+
<ul class="text-gray-400 mt-1 ml-4 space-y-1">
|
|
1105
|
+
<li>• 还没执行 <code>uni deploy</code></li>
|
|
1106
|
+
<li>• 部署时指定了不同的 <code>--dir</code> 目录</li>
|
|
1107
|
+
<li>• Dashboard 读取的 openclawDir 和部署的不一致</li>
|
|
1108
|
+
</ul>
|
|
1109
|
+
</div>
|
|
1110
|
+
|
|
1111
|
+
<div class="bg-surface rounded-lg p-4 border border-red-700/20">
|
|
1112
|
+
<div class="text-red-300 font-medium mb-2">❌ <code>openclaw agent</code> 执行失败</div>
|
|
1113
|
+
<p class="text-gray-400">常见原因:</p>
|
|
1114
|
+
<ul class="text-gray-400 mt-1 ml-4 space-y-1">
|
|
1115
|
+
<li>• API Key 未配置 — 运行 <code>openclaw config</code> 设置</li>
|
|
1116
|
+
<li>• Gateway 未启动 — 运行 <code>openclaw gateway run</code></li>
|
|
1117
|
+
<li>• Agent 的 SOUL.md 缺失 — 检查 workspace 目录</li>
|
|
1118
|
+
</ul>
|
|
1119
|
+
</div>
|
|
1120
|
+
|
|
1121
|
+
<div class="bg-surface rounded-lg p-4 border border-red-700/20">
|
|
1122
|
+
<div class="text-red-300 font-medium mb-2">❌ SUBMISSION.md 一直没有出现(轮询超时)</div>
|
|
1123
|
+
<p class="text-gray-400">说明 Agent 没有成功执行任务。检查:</p>
|
|
1124
|
+
<ul class="text-gray-400 mt-1 ml-4 space-y-1">
|
|
1125
|
+
<li>• OpenClaw Gateway 是否在运行:<code>openclaw gateway status</code></li>
|
|
1126
|
+
<li>• Agent 是否能收到 TASK.md:<code>cat ~/.openclaw/workspace-{id}/TASK.md</code></li>
|
|
1127
|
+
<li>• 查看 Gateway 日志:<code>openclaw logs --tail 100</code></li>
|
|
1128
|
+
<li>• 超时时间是否太短 — 增加 <code>timeoutMs</code> 值</li>
|
|
1129
|
+
</ul>
|
|
1130
|
+
</div>
|
|
1131
|
+
|
|
1132
|
+
<div class="bg-surface rounded-lg p-4 border border-yellow-700/20">
|
|
1133
|
+
<div class="text-yellow-300 font-medium mb-2">💡 完全重新开始</div>
|
|
1134
|
+
<p class="text-gray-400">如果一切混乱,想从头来过:</p>
|
|
1135
|
+
${codeBlock(`# 1. 清理已注册的 Uni
|
|
1136
|
+
npx uni cleanup zhenhuan-palace
|
|
1137
|
+
|
|
1138
|
+
# 2. 重新部署
|
|
1139
|
+
npx uni deploy universe.yaml
|
|
1140
|
+
|
|
1141
|
+
# 3. 验证
|
|
1142
|
+
openclaw agents list
|
|
1143
|
+
npx uni list`)}
|
|
1144
|
+
</div>
|
|
1145
|
+
|
|
1146
|
+
</div>
|
|
1147
|
+
</div>
|
|
1148
|
+
|
|
1149
|
+
</div>
|
|
1150
|
+
`;
|
|
1151
|
+
return renderLayout('用户手册', body, 'guide');
|
|
1152
|
+
}
|
|
1153
|
+
export function renderUniDetailPage(data) {
|
|
1154
|
+
const { entry, config, workspaceStatus } = data;
|
|
1155
|
+
const agentsTableHtml = config
|
|
1156
|
+
? config.agents.map(agent => {
|
|
1157
|
+
const ws = workspaceStatus[agent.id] ?? { hasSoul: false, hasTask: false, hasSubmission: false };
|
|
1158
|
+
return `
|
|
1159
|
+
<tr class="border-b border-gray-700/30 hover:bg-surface-lighter/50 transition">
|
|
1160
|
+
<td class="py-3 px-4">
|
|
1161
|
+
<a href="/uni/${encodeURIComponent(entry.id)}/agent/${encodeURIComponent(agent.id)}" class="text-accent-light hover:underline font-medium">${escapeHtml(agent.id)}</a>
|
|
1162
|
+
</td>
|
|
1163
|
+
<td class="py-3 px-4 text-gray-300">${escapeHtml(agent.name)}</td>
|
|
1164
|
+
<td class="py-3 px-4 text-gray-400">${escapeHtml(agent.role.title)}</td>
|
|
1165
|
+
<td class="py-3 px-4 text-center">${agent.rank ?? '-'}</td>
|
|
1166
|
+
<td class="py-3 px-4 text-center">
|
|
1167
|
+
<span class="${ws.hasSoul ? 'text-green-400' : 'text-red-400'}">${ws.hasSoul ? '✓' : '✗'}</span>
|
|
1168
|
+
</td>
|
|
1169
|
+
<td class="py-3 px-4 text-center">
|
|
1170
|
+
<span class="${ws.hasTask ? 'text-yellow-400' : 'text-gray-600'}">${ws.hasTask ? '⏳' : '—'}</span>
|
|
1171
|
+
</td>
|
|
1172
|
+
<td class="py-3 px-4 text-center">
|
|
1173
|
+
<span class="${ws.hasSubmission ? 'text-blue-400' : 'text-gray-600'}">${ws.hasSubmission ? '📝' : '—'}</span>
|
|
1174
|
+
</td>
|
|
1175
|
+
</tr>`;
|
|
1176
|
+
}).join('')
|
|
1177
|
+
: '<tr><td colspan="7" class="py-8 text-center text-gray-500">无法加载 Universe 配置</td></tr>';
|
|
1178
|
+
// Relationship type mappings for broader coverage
|
|
1179
|
+
const typeEmoji = {
|
|
1180
|
+
superior: '👆', subordinate: '👇', peer: '🤝', competitive: '⚔️',
|
|
1181
|
+
reviewer: '🔍', advisor: '💡', ally: '🛡️', rival: '⚔️',
|
|
1182
|
+
mentor: '🎓', delegate: '📋', supervises: '👆', collaborates: '🤝',
|
|
1183
|
+
competes: '⚔️', advises: '💡', audits: '🔍',
|
|
1184
|
+
};
|
|
1185
|
+
const relationshipsHtml = config && config.relationships.length > 0
|
|
1186
|
+
? `<div class="bg-surface-light rounded-xl p-6 border border-gray-700/50 mt-6">
|
|
1187
|
+
<h2 class="text-lg font-semibold text-white mb-4">🔗 关系图谱</h2>
|
|
1188
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
|
1189
|
+
${config.relationships.map(rel => `
|
|
1190
|
+
<div class="bg-surface rounded-lg p-3 border border-gray-700/30 flex items-center gap-3">
|
|
1191
|
+
<span class="text-lg">${typeEmoji[rel.type] ?? '↔'}</span>
|
|
1192
|
+
<div class="text-sm">
|
|
1193
|
+
<a href="/uni/${encodeURIComponent(entry.id)}/agent/${encodeURIComponent(rel.from)}" class="text-accent-light hover:underline">${escapeHtml(rel.from)}</a>
|
|
1194
|
+
<span class="text-gray-500 mx-1">${rel.type}</span>
|
|
1195
|
+
<a href="/uni/${encodeURIComponent(entry.id)}/agent/${encodeURIComponent(rel.to)}" class="text-accent-light hover:underline">${escapeHtml(rel.to)}</a>
|
|
1196
|
+
${rel.weight !== undefined ? `<span class="text-gray-600 ml-1">(${rel.weight})</span>` : ''}
|
|
1197
|
+
</div>
|
|
1198
|
+
</div>`).join('')}
|
|
1199
|
+
</div>
|
|
1200
|
+
</div>`
|
|
1201
|
+
: '';
|
|
1202
|
+
const body = `
|
|
1203
|
+
<div class="mb-6">
|
|
1204
|
+
<a href="/" class="text-gray-500 hover:text-gray-300 text-sm transition">← 返回首页</a>
|
|
1205
|
+
</div>
|
|
1206
|
+
|
|
1207
|
+
<div class="flex items-start justify-between mb-6">
|
|
1208
|
+
<div>
|
|
1209
|
+
<h1 class="text-3xl font-bold text-white mb-1">${escapeHtml(entry.id)}</h1>
|
|
1210
|
+
<p class="text-gray-400">${escapeHtml(entry.description)}</p>
|
|
1211
|
+
</div>
|
|
1212
|
+
<div class="flex gap-3">
|
|
1213
|
+
<button onclick="uniAction('reset', '${entry.id}')" class="px-4 py-2 bg-yellow-600/20 text-yellow-300 rounded-lg hover:bg-yellow-600/30 transition text-sm">🔄 重置</button>
|
|
1214
|
+
<button onclick="uniAction('cleanup', '${entry.id}')" class="px-4 py-2 bg-red-600/20 text-red-300 rounded-lg hover:bg-red-600/30 transition text-sm">🗑️ 清理</button>
|
|
1215
|
+
</div>
|
|
1216
|
+
</div>
|
|
1217
|
+
|
|
1218
|
+
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
|
|
1219
|
+
<div class="bg-surface-light rounded-xl p-4 border border-gray-700/50">
|
|
1220
|
+
<div class="text-sm text-gray-400">类型</div>
|
|
1221
|
+
<div class="text-white font-medium mt-1">${entry.type}</div>
|
|
1222
|
+
</div>
|
|
1223
|
+
<div class="bg-surface-light rounded-xl p-4 border border-gray-700/50">
|
|
1224
|
+
<div class="text-sm text-gray-400">版本</div>
|
|
1225
|
+
<div class="text-white font-medium mt-1">v${escapeHtml(entry.version)}</div>
|
|
1226
|
+
</div>
|
|
1227
|
+
<div class="bg-surface-light rounded-xl p-4 border border-gray-700/50">
|
|
1228
|
+
<div class="text-sm text-gray-400">Agent 数</div>
|
|
1229
|
+
<div class="text-white font-medium mt-1">${entry.agentIds.length}</div>
|
|
1230
|
+
</div>
|
|
1231
|
+
<div class="bg-surface-light rounded-xl p-4 border border-gray-700/50">
|
|
1232
|
+
<div class="text-sm text-gray-400">部署时间</div>
|
|
1233
|
+
<div class="text-white font-medium mt-1">${formatDate(entry.deployedAt)}</div>
|
|
1234
|
+
</div>
|
|
1235
|
+
</div>
|
|
1236
|
+
|
|
1237
|
+
<!-- Agent Table -->
|
|
1238
|
+
<div class="bg-surface-light rounded-xl border border-gray-700/50 overflow-hidden">
|
|
1239
|
+
<div class="px-6 py-4 border-b border-gray-700/50">
|
|
1240
|
+
<h2 class="text-lg font-semibold text-white">🤖 Agents</h2>
|
|
1241
|
+
</div>
|
|
1242
|
+
<table class="w-full text-sm">
|
|
1243
|
+
<thead>
|
|
1244
|
+
<tr class="text-gray-500 text-left border-b border-gray-700/50">
|
|
1245
|
+
<th class="py-3 px-4 font-medium">ID</th>
|
|
1246
|
+
<th class="py-3 px-4 font-medium">名称</th>
|
|
1247
|
+
<th class="py-3 px-4 font-medium">角色</th>
|
|
1248
|
+
<th class="py-3 px-4 font-medium text-center">Rank</th>
|
|
1249
|
+
<th class="py-3 px-4 font-medium text-center">SOUL</th>
|
|
1250
|
+
<th class="py-3 px-4 font-medium text-center">TASK</th>
|
|
1251
|
+
<th class="py-3 px-4 font-medium text-center">SUB</th>
|
|
1252
|
+
</tr>
|
|
1253
|
+
</thead>
|
|
1254
|
+
<tbody>
|
|
1255
|
+
${agentsTableHtml}
|
|
1256
|
+
</tbody>
|
|
1257
|
+
</table>
|
|
1258
|
+
</div>
|
|
1259
|
+
|
|
1260
|
+
${relationshipsHtml}
|
|
1261
|
+
|
|
1262
|
+
<div class="mt-6 bg-surface-light rounded-xl p-4 border border-gray-700/50">
|
|
1263
|
+
<div class="text-sm text-gray-400">Spec 路径</div>
|
|
1264
|
+
<code class="text-accent-light text-sm">${escapeHtml(entry.specPath)}</code>
|
|
1265
|
+
</div>
|
|
1266
|
+
|
|
1267
|
+
<script>
|
|
1268
|
+
async function uniAction(action, id) {
|
|
1269
|
+
if (action === 'cleanup' && !confirm('确定要清理此 Uni?所有 workspace 和 agent 目录将被删除。')) return;
|
|
1270
|
+
if (action === 'reset' && !confirm('确定要重置此 Uni?运行时数据(sessions/TASK.md/SUBMISSION.md)将被清除。')) return;
|
|
1271
|
+
const res = await fetch('/api/unis/' + encodeURIComponent(id) + '/' + action, { method: 'POST' });
|
|
1272
|
+
const data = await res.json();
|
|
1273
|
+
alert(JSON.stringify(data, null, 2));
|
|
1274
|
+
if (action === 'cleanup') window.location.href = '/';
|
|
1275
|
+
else window.location.reload();
|
|
1276
|
+
}
|
|
1277
|
+
</script>
|
|
1278
|
+
`;
|
|
1279
|
+
return renderLayout(entry.id, body);
|
|
1280
|
+
}
|
|
1281
|
+
export function renderAgentDetailPage(data) {
|
|
1282
|
+
const { uniId, agentId, config, workspace } = data;
|
|
1283
|
+
const agent = config?.agents.find(a => a.id === agentId);
|
|
1284
|
+
if (!agent) {
|
|
1285
|
+
return renderLayout('Agent Not Found', `
|
|
1286
|
+
<div class="text-center py-20">
|
|
1287
|
+
<div class="text-6xl mb-4">❓</div>
|
|
1288
|
+
<h2 class="text-xl text-gray-400">Agent "${escapeHtml(agentId)}" 未找到</h2>
|
|
1289
|
+
<a href="/uni/${encodeURIComponent(uniId)}" class="text-accent-light hover:underline mt-4 block">返回 Uni</a>
|
|
1290
|
+
</div>
|
|
1291
|
+
`);
|
|
1292
|
+
}
|
|
1293
|
+
const relationships = config?.relationships.filter(r => r.from === agentId || r.to === agentId) ?? [];
|
|
1294
|
+
const traitsHtml = agent.traits
|
|
1295
|
+
? Object.entries(agent.traits).map(([key, val]) => `
|
|
1296
|
+
<div class="flex items-center justify-between py-2 border-b border-gray-700/30">
|
|
1297
|
+
<span class="text-gray-400">${escapeHtml(key)}</span>
|
|
1298
|
+
<div class="flex items-center gap-2">
|
|
1299
|
+
<div class="w-24 bg-surface rounded-full h-2">
|
|
1300
|
+
<div class="bg-accent rounded-full h-2" style="width: ${Math.min(100, val)}%"></div>
|
|
1301
|
+
</div>
|
|
1302
|
+
<span class="text-white text-sm w-8 text-right">${val}</span>
|
|
1303
|
+
</div>
|
|
1304
|
+
</div>
|
|
1305
|
+
`).join('')
|
|
1306
|
+
: '<p class="text-gray-500">无特征数据</p>';
|
|
1307
|
+
const relsHtml = relationships.length > 0
|
|
1308
|
+
? relationships.map(rel => {
|
|
1309
|
+
const other = rel.from === agentId ? rel.to : rel.from;
|
|
1310
|
+
const direction = rel.from === agentId ? '→' : '←';
|
|
1311
|
+
return `
|
|
1312
|
+
<div class="flex items-center gap-3 py-2 border-b border-gray-700/30">
|
|
1313
|
+
<span class="text-gray-400">${direction}</span>
|
|
1314
|
+
<a href="/uni/${encodeURIComponent(uniId)}/agent/${encodeURIComponent(other)}" class="text-accent-light hover:underline">${escapeHtml(other)}</a>
|
|
1315
|
+
<span class="badge bg-gray-700 text-gray-300">${rel.type}</span>
|
|
1316
|
+
${rel.weight !== undefined ? `<span class="text-gray-500 text-sm">(${rel.weight})</span>` : ''}
|
|
1317
|
+
</div>`;
|
|
1318
|
+
}).join('')
|
|
1319
|
+
: '<p class="text-gray-500">无关系数据</p>';
|
|
1320
|
+
const body = `
|
|
1321
|
+
<div class="mb-6">
|
|
1322
|
+
<a href="/uni/${encodeURIComponent(uniId)}" class="text-gray-500 hover:text-gray-300 text-sm transition">← 返回 ${escapeHtml(uniId)}</a>
|
|
1323
|
+
</div>
|
|
1324
|
+
|
|
1325
|
+
<h1 class="text-3xl font-bold text-white mb-1">${escapeHtml(agent.name)}</h1>
|
|
1326
|
+
<p class="text-gray-400 mb-6">${escapeHtml(agent.role.title)} · Rank ${agent.rank ?? 'N/A'}</p>
|
|
1327
|
+
|
|
1328
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
1329
|
+
<!-- Left column -->
|
|
1330
|
+
<div class="space-y-6">
|
|
1331
|
+
<div class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
1332
|
+
<h2 class="text-lg font-semibold text-white mb-4">📋 职责</h2>
|
|
1333
|
+
${agent.role.duties.length > 0
|
|
1334
|
+
? `<ul class="space-y-2">${agent.role.duties.map(d => `<li class="text-gray-300 text-sm flex gap-2"><span class="text-gray-500">•</span>${escapeHtml(d)}</li>`).join('')}</ul>`
|
|
1335
|
+
: '<p class="text-gray-500">无职责定义</p>'}
|
|
1336
|
+
</div>
|
|
1337
|
+
|
|
1338
|
+
<div class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
1339
|
+
<h2 class="text-lg font-semibold text-white mb-4">🔐 权限</h2>
|
|
1340
|
+
${agent.role.permissions.length > 0
|
|
1341
|
+
? `<div class="flex flex-wrap gap-2">${agent.role.permissions.map(p => `<span class="badge bg-accent/20 text-accent-light">${escapeHtml(p)}</span>`).join('')}</div>`
|
|
1342
|
+
: '<p class="text-gray-500">无权限定义</p>'}
|
|
1343
|
+
</div>
|
|
1344
|
+
|
|
1345
|
+
${agent.capabilities ? `
|
|
1346
|
+
<div class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
1347
|
+
<h2 class="text-lg font-semibold text-white mb-4">⚡ 能力</h2>
|
|
1348
|
+
<div class="flex flex-wrap gap-2">
|
|
1349
|
+
${agent.capabilities.map(c => `<span class="badge bg-green-500/20 text-green-300">${escapeHtml(c)}</span>`).join('')}
|
|
1350
|
+
</div>
|
|
1351
|
+
</div>
|
|
1352
|
+
` : ''}
|
|
1353
|
+
</div>
|
|
1354
|
+
|
|
1355
|
+
<!-- Right column -->
|
|
1356
|
+
<div class="space-y-6">
|
|
1357
|
+
<div class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
1358
|
+
<h2 class="text-lg font-semibold text-white mb-4">📊 特征值</h2>
|
|
1359
|
+
${traitsHtml}
|
|
1360
|
+
</div>
|
|
1361
|
+
|
|
1362
|
+
<div class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
1363
|
+
<h2 class="text-lg font-semibold text-white mb-4">🔗 关系</h2>
|
|
1364
|
+
${relsHtml}
|
|
1365
|
+
</div>
|
|
1366
|
+
|
|
1367
|
+
<div class="bg-surface-light rounded-xl p-6 border border-gray-700/50">
|
|
1368
|
+
<h2 class="text-lg font-semibold text-white mb-4">📂 Workspace 状态</h2>
|
|
1369
|
+
<div class="space-y-2 text-sm">
|
|
1370
|
+
<div class="flex justify-between"><span class="text-gray-400">SOUL.md</span><span class="${workspace.hasSoul ? 'text-green-400' : 'text-red-400'}">${workspace.hasSoul ? '✓ 存在' : '✗ 缺失'}</span></div>
|
|
1371
|
+
<div class="flex justify-between"><span class="text-gray-400">TASK.md</span><span class="${workspace.hasTask ? 'text-yellow-400' : 'text-gray-600'}">${workspace.hasTask ? '⏳ 有任务' : '— 空闲'}</span></div>
|
|
1372
|
+
<div class="flex justify-between"><span class="text-gray-400">SUBMISSION.md</span><span class="${workspace.hasSubmission ? 'text-blue-400' : 'text-gray-600'}">${workspace.hasSubmission ? '📝 已提交' : '— 无'}</span></div>
|
|
1373
|
+
</div>
|
|
1374
|
+
</div>
|
|
1375
|
+
</div>
|
|
1376
|
+
</div>
|
|
1377
|
+
`;
|
|
1378
|
+
return renderLayout(`${agent.name} — ${uniId}`, body);
|
|
1379
|
+
}
|
|
1380
|
+
// ─── Manage Page ──────────────────────────────────
|
|
1381
|
+
export function renderManagePage(unis, healthStatus) {
|
|
1382
|
+
const body = `
|
|
1383
|
+
<div class="mb-8">
|
|
1384
|
+
<h1 class="text-3xl font-bold text-white mb-2">管理中心</h1>
|
|
1385
|
+
<p class="text-gray-400">Uni 生命周期管理与健康检查</p>
|
|
1386
|
+
</div>
|
|
1387
|
+
|
|
1388
|
+
<!-- Health Check -->
|
|
1389
|
+
<div class="bg-surface-light rounded-xl p-6 border border-gray-700/50 mb-8">
|
|
1390
|
+
<h2 class="text-lg font-semibold text-white mb-4">🏥 健康状态</h2>
|
|
1391
|
+
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 text-sm">
|
|
1392
|
+
<div>
|
|
1393
|
+
<div class="text-gray-400">OpenClaw 目录</div>
|
|
1394
|
+
<code class="text-accent-light text-xs">${escapeHtml(healthStatus.openclawDir)}</code>
|
|
1395
|
+
</div>
|
|
1396
|
+
<div>
|
|
1397
|
+
<div class="text-gray-400">openclaw.json</div>
|
|
1398
|
+
<span class="${healthStatus.configExists ? 'text-green-400' : 'text-red-400'}">${healthStatus.configExists ? '✓ 正常' : '✗ 缺失'}</span>
|
|
1399
|
+
</div>
|
|
1400
|
+
<div>
|
|
1401
|
+
<div class="text-gray-400">uni-registry.json</div>
|
|
1402
|
+
<span class="${healthStatus.registryExists ? 'text-green-400' : 'text-red-400'}">${healthStatus.registryExists ? '✓ 正常' : '✗ 缺失'}</span>
|
|
1403
|
+
</div>
|
|
1404
|
+
<div>
|
|
1405
|
+
<div class="text-gray-400">Config 中 Agent 数</div>
|
|
1406
|
+
<span class="text-white">${healthStatus.totalAgentsInConfig}</span>
|
|
1407
|
+
</div>
|
|
1408
|
+
</div>
|
|
1409
|
+
</div>
|
|
1410
|
+
|
|
1411
|
+
<!-- Uni List -->
|
|
1412
|
+
<div class="bg-surface-light rounded-xl border border-gray-700/50 overflow-hidden">
|
|
1413
|
+
<div class="px-6 py-4 border-b border-gray-700/50 flex items-center justify-between">
|
|
1414
|
+
<h2 class="text-lg font-semibold text-white">🌌 所有 Uni</h2>
|
|
1415
|
+
<span class="text-gray-500 text-sm">${unis.length} 个</span>
|
|
1416
|
+
</div>
|
|
1417
|
+
${unis.length === 0
|
|
1418
|
+
? '<div class="py-12 text-center text-gray-500">暂无已注册的 Uni</div>'
|
|
1419
|
+
: `<table class="w-full text-sm">
|
|
1420
|
+
<thead>
|
|
1421
|
+
<tr class="text-gray-500 text-left border-b border-gray-700/50">
|
|
1422
|
+
<th class="py-3 px-4 font-medium">ID</th>
|
|
1423
|
+
<th class="py-3 px-4 font-medium">类型</th>
|
|
1424
|
+
<th class="py-3 px-4 font-medium text-center">Agents</th>
|
|
1425
|
+
<th class="py-3 px-4 font-medium">版本</th>
|
|
1426
|
+
<th class="py-3 px-4 font-medium">最后更新</th>
|
|
1427
|
+
<th class="py-3 px-4 font-medium text-right">操作</th>
|
|
1428
|
+
</tr>
|
|
1429
|
+
</thead>
|
|
1430
|
+
<tbody>
|
|
1431
|
+
${unis.map(uni => `
|
|
1432
|
+
<tr class="border-b border-gray-700/30 hover:bg-surface-lighter/50">
|
|
1433
|
+
<td class="py-3 px-4">
|
|
1434
|
+
<a href="/uni/${encodeURIComponent(uni.id)}" class="text-accent-light hover:underline">${escapeHtml(uni.id)}</a>
|
|
1435
|
+
</td>
|
|
1436
|
+
<td class="py-3 px-4 text-gray-400">${uni.type}</td>
|
|
1437
|
+
<td class="py-3 px-4 text-center text-gray-300">${uni.agentIds.length}</td>
|
|
1438
|
+
<td class="py-3 px-4 text-gray-400">v${escapeHtml(uni.version)}</td>
|
|
1439
|
+
<td class="py-3 px-4 text-gray-500">${formatDate(uni.updatedAt)}</td>
|
|
1440
|
+
<td class="py-3 px-4 text-right">
|
|
1441
|
+
<button onclick="uniAction('reset', '${uni.id}')" class="text-yellow-400 hover:text-yellow-300 mr-3" title="重置">🔄</button>
|
|
1442
|
+
<button onclick="uniAction('cleanup', '${uni.id}')" class="text-red-400 hover:text-red-300" title="清理">🗑️</button>
|
|
1443
|
+
</td>
|
|
1444
|
+
</tr>
|
|
1445
|
+
`).join('')}
|
|
1446
|
+
</tbody>
|
|
1447
|
+
</table>`}
|
|
1448
|
+
</div>
|
|
1449
|
+
|
|
1450
|
+
<script>
|
|
1451
|
+
async function uniAction(action, id) {
|
|
1452
|
+
if (action === 'cleanup' && !confirm('确定要清理 ' + id + '?所有 workspace 和 agent 目录将被删除。')) return;
|
|
1453
|
+
if (action === 'reset' && !confirm('确定要重置 ' + id + '?运行时数据将被清除。')) return;
|
|
1454
|
+
const res = await fetch('/api/unis/' + encodeURIComponent(id) + '/' + action, { method: 'POST' });
|
|
1455
|
+
const data = await res.json();
|
|
1456
|
+
alert(JSON.stringify(data, null, 2));
|
|
1457
|
+
window.location.reload();
|
|
1458
|
+
}
|
|
1459
|
+
</script>
|
|
1460
|
+
`;
|
|
1461
|
+
return renderLayout('管理中心', body, 'manage');
|
|
1462
|
+
}
|
|
1463
|
+
// ─── Utilities ────────────────────────────────────
|
|
1464
|
+
function escapeHtml(str) {
|
|
1465
|
+
return str
|
|
1466
|
+
.replace(/&/g, '&')
|
|
1467
|
+
.replace(/</g, '<')
|
|
1468
|
+
.replace(/>/g, '>')
|
|
1469
|
+
.replace(/"/g, '"')
|
|
1470
|
+
.replace(/'/g, ''');
|
|
1471
|
+
}
|
|
1472
|
+
function formatDate(iso) {
|
|
1473
|
+
try {
|
|
1474
|
+
const d = new Date(iso);
|
|
1475
|
+
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')} ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
|
|
1476
|
+
}
|
|
1477
|
+
catch {
|
|
1478
|
+
return iso;
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
//# sourceMappingURL=templates.js.map
|