@bolloon/bolloon-agent 0.1.37 → 0.1.39

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 (31) hide show
  1. package/dist/agents/constraint-layer.js +1 -2
  2. package/package.json +1 -1
  3. package/scripts/auto-evolve-oneshot.sh +155 -0
  4. package/scripts/auto-evolve-snapshot.sh +136 -0
  5. package/scripts/build-cli.js +216 -0
  6. package/scripts/detect-schema-changes.sh +48 -0
  7. package/scripts/postinstall.js +153 -0
  8. package/dist/bollharness-integration/llm/pi-ai.js +0 -397
  9. package/dist/bollharness-integration/pi-ecosystem-colony/index.js +0 -365
  10. package/dist/bollharness-integration/pi-ecosystem-goals/index.js +0 -458
  11. package/dist/bollharness-integration/pi-ecosystem-judgment/decision.js +0 -300
  12. package/dist/bollharness-integration/pi-ecosystem-judgment/distillation.js +0 -291
  13. package/dist/bollharness-integration/pi-ecosystem-judgment/index.js +0 -445
  14. package/dist/bollharness-integration/pi-ecosystem-mcp/index.js +0 -331
  15. package/dist/bollharness-integration/pi-ecosystem-subagents/index.js +0 -303
  16. package/dist/constraints/commands.js +0 -100
  17. package/dist/constraints/permissions.js +0 -37
  18. package/dist/constraints/runtime.js +0 -135
  19. package/dist/constraints/session.js +0 -48
  20. package/dist/constraints/system-init.js +0 -51
  21. package/dist/constraints/tools.js +0 -104
  22. package/dist/llm/minimax-provider.js +0 -46
  23. package/dist/llm/minimax.js +0 -45
  24. package/dist/pi-ecosystem-colony/index.js +0 -365
  25. package/dist/runtime/context/minimax-prompt.js +0 -178
  26. package/dist/runtime/context/sys-prompt.js +0 -1
  27. package/dist/social/ant-colony/AdaptiveHeartbeat.js +0 -101
  28. package/dist/social/ant-colony/PheromoneEngine.js +0 -227
  29. package/dist/social/ant-colony/index.js +0 -6
  30. package/dist/social/ant-colony/types.js +0 -24
  31. package/dist/utils/double.js +0 -6
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Postinstall 脚本
3
+ * npm 安装后自动执行
4
+ *
5
+ * 主要任务:
6
+ * 1. 确保 bin 目录存在且可执行
7
+ * 2. 初始化本地配置
8
+ * 3. 检查依赖完整性
9
+ */
10
+
11
+ import * as fs from 'fs';
12
+ import * as path from 'path';
13
+ import { fileURLToPath } from 'url';
14
+
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = path.dirname(__filename);
17
+ const rootDir = path.join(__dirname, '..');
18
+
19
+ const RESET = '\x1b[0m';
20
+ const GREEN = '\x1b[32m';
21
+ const YELLOW = '\x1b[33m';
22
+ const CYAN = '\x1b[36m';
23
+
24
+ function log(msg, color = RESET) {
25
+ console.log(color + msg + RESET);
26
+ }
27
+
28
+ function initUserDirs() {
29
+ // 创建用户数据目录
30
+ const home = process.env.HOME || process.env.USERPROFILE || '/tmp';
31
+ const bolloonDir = path.join(home, '.bolloon');
32
+
33
+ const dirs = [
34
+ bolloonDir,
35
+ path.join(bolloonDir, 'sessions'),
36
+ path.join(bolloonDir, 'peer-store'),
37
+ ];
38
+
39
+ for (const dir of dirs) {
40
+ if (!fs.existsSync(dir)) {
41
+ fs.mkdirSync(dir, { recursive: true });
42
+ log(` ✓ 创建目录: ${dir}`, GREEN);
43
+ }
44
+ }
45
+
46
+ // 初始化配置文件
47
+ const configPath = path.join(bolloonDir, 'config.json');
48
+ if (!fs.existsSync(configPath)) {
49
+ const defaultConfig = {
50
+ version: '0.1.12',
51
+ initializedAt: new Date().toISOString(),
52
+ defaults: {
53
+ port: 54188,
54
+ theme: 'dark',
55
+ autoConnect: true,
56
+ },
57
+ providers: {
58
+ minimax: { enabled: false },
59
+ openai: { enabled: false },
60
+ anthropic: { enabled: false },
61
+ }
62
+ };
63
+ fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
64
+ log(` ✓ 创建配置: ${configPath}`, GREEN);
65
+ }
66
+
67
+ return bolloonDir;
68
+ }
69
+
70
+ function checkNativeDeps() {
71
+ // 检查必要的原生依赖
72
+ const nativeDeps = [
73
+ 'libp2p',
74
+ '@diap/sdk',
75
+ ];
76
+
77
+ let allOk = true;
78
+
79
+ for (const dep of nativeDeps) {
80
+ const depPath = path.join(rootDir, 'node_modules', dep);
81
+ if (!fs.existsSync(depPath)) {
82
+ log(` ⚠ 缺少依赖: ${dep}`, YELLOW);
83
+ allOk = false;
84
+ }
85
+ }
86
+
87
+ return allOk;
88
+ }
89
+
90
+ function setupPlatform() {
91
+ const platform = process.platform;
92
+
93
+ log(`\n 平台: ${platform}`, CYAN);
94
+
95
+ if (platform === 'win32') {
96
+ // Windows: 确保 .cmd 文件存在
97
+ const binDir = path.join(rootDir, 'bin');
98
+ const cmdPath = path.join(binDir, 'bolloon.cmd');
99
+
100
+ if (fs.existsSync(binDir) && !fs.existsSync(cmdPath)) {
101
+ const cmdContent = `@echo off
102
+ node "%~dp0..\\dist\\cli.js" %*
103
+ `;
104
+ fs.writeFileSync(cmdPath, cmdContent);
105
+ log(' ✓ Windows 入口已创建', GREEN);
106
+ }
107
+ } else {
108
+ // Unix/Linux/Mac: 确保 bin 文件可执行
109
+ const binDir = path.join(rootDir, 'bin');
110
+ const binPath = path.join(binDir, 'bolloon.js');
111
+
112
+ if (fs.existsSync(binPath)) {
113
+ try {
114
+ fs.chmodSync(binPath, 0o755);
115
+ log(' ✓ bin/bolloon.js 已设为可执行', GREEN);
116
+ } catch (err) {
117
+ log(` ⚠ 无法设置执行权限: ${err.message}`, YELLOW);
118
+ }
119
+ }
120
+ }
121
+ }
122
+
123
+ function main() {
124
+ console.log('\n📦 Bolloon 安装后处理...\n');
125
+
126
+ try {
127
+ // 1. 初始化用户目录
128
+ const bolloonDir = initUserDirs();
129
+ log(` ✓ 用户数据目录: ${bolloonDir}`, GREEN);
130
+
131
+ // 2. 检查依赖
132
+ const depsOk = checkNativeDeps();
133
+ if (!depsOk) {
134
+ log('\n ⚠ 部分依赖缺失,建议运行: npm install', YELLOW);
135
+ }
136
+
137
+ // 3. 平台特定设置
138
+ setupPlatform();
139
+
140
+ console.log('\n✅ 安装完成!\n');
141
+ console.log(' 使用方式:');
142
+ console.log(' bolloon # 启动 GUI');
143
+ console.log(' bolloon --web # 启动 Web UI');
144
+ console.log(' bolloon --cli # 命令行模式');
145
+ console.log(' bolloon --help # 显示帮助\n');
146
+ console.log(` 配置文件: ${path.join(bolloonDir, 'config.json')}\n`);
147
+ } catch (err) {
148
+ console.error('\n❌ 安装后处理失败:', err.message);
149
+ console.error(' 这通常不影响基本功能,继续安装...\n');
150
+ }
151
+ }
152
+
153
+ main();
@@ -1,397 +0,0 @@
1
- export class PiAIModel {
2
- config;
3
- provider;
4
- constructor(config) {
5
- this.config = config;
6
- this.provider = config.provider;
7
- }
8
- async chat(message, context) {
9
- const systemPrompt = this.buildSystemPrompt(context);
10
- const messages = [
11
- { role: 'system', content: systemPrompt },
12
- { role: 'user', content: message }
13
- ];
14
- try {
15
- const response = await this.generateText({
16
- messages,
17
- temperature: 0.8
18
- });
19
- return { reply: response };
20
- }
21
- catch (error) {
22
- console.error('PiAI chat error:', error);
23
- return { reply: '抱歉,AI服务暂时不可用。' };
24
- }
25
- }
26
- async summarize(text, context) {
27
- const prompt = this.buildSummarizePrompt(text, context);
28
- try {
29
- const response = await this.generateText({
30
- messages: [
31
- { role: 'system', content: 'You are a professional document summarizer.' },
32
- { role: 'user', content: prompt }
33
- ],
34
- temperature: 0.7
35
- });
36
- const qualityScore = this.estimateQuality(text, response);
37
- return { summary: response, qualityScore };
38
- }
39
- catch (error) {
40
- console.error('PiAI summarize error:', error);
41
- return {
42
- summary: text.substring(0, 500) + '...',
43
- qualityScore: 0.5
44
- };
45
- }
46
- }
47
- async improveContent(content, requirements, context) {
48
- const prompt = this.buildImprovePrompt(content, requirements, context);
49
- try {
50
- const response = await this.generateText({
51
- messages: [
52
- { role: 'system', content: 'You are a professional document editor and improver.' },
53
- { role: 'user', content: prompt }
54
- ],
55
- temperature: 0.8
56
- });
57
- return response;
58
- }
59
- catch (error) {
60
- console.error('PiAI improve error:', error);
61
- return content;
62
- }
63
- }
64
- async generateText(options) {
65
- const { messages, temperature = 0.7, maxTokens = 4096 } = options;
66
- switch (this.provider) {
67
- case 'openai':
68
- case 'minimax':
69
- return this.callOpenAI(messages, temperature, maxTokens);
70
- case 'anthropic':
71
- return this.callAnthropic(messages, temperature, maxTokens);
72
- case 'ollama':
73
- return this.callOllama(messages, temperature);
74
- case 'openrouter':
75
- return this.callOpenRouter(messages, temperature, maxTokens);
76
- case 'gemini':
77
- return this.callGemini(messages, temperature, maxTokens);
78
- case 'local':
79
- return this.callLocal(messages, temperature);
80
- default:
81
- throw new Error(`Unsupported provider: ${this.provider}`);
82
- }
83
- }
84
- getApiKey() {
85
- return this.config.apiKey || this.getEnvApiKey();
86
- }
87
- getEnvApiKey() {
88
- const envVars = {
89
- openai: process.env.OPENAI_API_KEY || '',
90
- anthropic: process.env.ANTHROPIC_API_KEY || '',
91
- ollama: '',
92
- openrouter: process.env.OPENROUTER_API_KEY || '',
93
- gemini: process.env.GEMINI_API_KEY || '',
94
- minimax: process.env.MINIMAX_API_KEY || '',
95
- local: ''
96
- };
97
- return envVars[this.provider] || '';
98
- }
99
- getBaseUrl() {
100
- if (this.config.baseUrl) {
101
- return this.config.baseUrl;
102
- }
103
- const baseUrls = {
104
- openai: 'https://api.openai.com/v1',
105
- anthropic: 'https://api.anthropic.com/v1',
106
- ollama: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',
107
- openrouter: 'https://openrouter.ai/api/v1',
108
- gemini: 'https://generativelanguage.googleapis.com/v1beta',
109
- minimax: 'https://api.minimaxi.com/v1',
110
- local: 'http://localhost:11434'
111
- };
112
- return baseUrls[this.provider];
113
- }
114
- mapModel() {
115
- const modelMap = {
116
- openai: this.config.model || 'gpt-4',
117
- anthropic: this.config.model || 'claude-3-5-sonnet-20241022',
118
- ollama: this.config.model || 'llama3.2',
119
- openrouter: this.config.model || 'anthropic/claude-3.5-sonnet',
120
- gemini: this.config.model || 'gemini-2.0-flash',
121
- minimax: this.config.model || 'MiniMax-M2.7',
122
- local: this.config.model || 'llama3.2'
123
- };
124
- return modelMap[this.provider];
125
- }
126
- async callOpenAI(messages, temperature, maxTokens) {
127
- const apiKey = this.getApiKey();
128
- if (!apiKey) {
129
- throw new Error('OPENAI_API_KEY not set');
130
- }
131
- const response = await fetch(`${this.getBaseUrl()}/chat/completions`, {
132
- method: 'POST',
133
- headers: {
134
- 'Content-Type': 'application/json',
135
- 'Authorization': `Bearer ${apiKey}`
136
- },
137
- body: JSON.stringify({
138
- model: this.mapModel(),
139
- messages,
140
- temperature,
141
- max_tokens: maxTokens
142
- })
143
- });
144
- if (!response.ok) {
145
- throw new Error(`OpenAI API error: ${response.status}`);
146
- }
147
- const data = await response.json();
148
- return data.choices?.[0]?.message?.content || '';
149
- }
150
- async callAnthropic(messages, temperature, maxTokens) {
151
- const apiKey = this.getApiKey();
152
- if (!apiKey) {
153
- throw new Error('ANTHROPIC_API_KEY not set');
154
- }
155
- const systemMessage = messages.find(m => m.role === 'system')?.content || '';
156
- const userMessages = messages.filter(m => m.role !== 'system');
157
- const response = await fetch(`${this.getBaseUrl()}/messages`, {
158
- method: 'POST',
159
- headers: {
160
- 'Content-Type': 'application/json',
161
- 'x-api-key': apiKey,
162
- 'anthropic-version': '2023-06-01',
163
- 'anthropic-dangerous-direct-browser-access': 'true'
164
- },
165
- body: JSON.stringify({
166
- model: this.mapModel(),
167
- messages: userMessages,
168
- system: systemMessage,
169
- temperature,
170
- max_tokens: maxTokens
171
- })
172
- });
173
- if (!response.ok) {
174
- throw new Error(`Anthropic API error: ${response.status}`);
175
- }
176
- const data = await response.json();
177
- return data.content?.[0]?.text || '';
178
- }
179
- async callOllama(messages, temperature) {
180
- const response = await fetch(`${this.getBaseUrl()}/api/chat`, {
181
- method: 'POST',
182
- headers: {
183
- 'Content-Type': 'application/json'
184
- },
185
- body: JSON.stringify({
186
- model: this.mapModel(),
187
- messages,
188
- temperature,
189
- stream: false
190
- })
191
- });
192
- if (!response.ok) {
193
- throw new Error(`Ollama API error: ${response.status}`);
194
- }
195
- const data = await response.json();
196
- return data.message?.content || '';
197
- }
198
- async callOpenRouter(messages, temperature, maxTokens) {
199
- const apiKey = this.getApiKey();
200
- if (!apiKey) {
201
- throw new Error('OPENROUTER_API_KEY not set');
202
- }
203
- const response = await fetch(`${this.getBaseUrl()}/chat/completions`, {
204
- method: 'POST',
205
- headers: {
206
- 'Content-Type': 'application/json',
207
- 'Authorization': `Bearer ${apiKey}`,
208
- 'HTTP-Referer': 'https://openclaw.ai',
209
- 'X-Title': 'OpenClaw'
210
- },
211
- body: JSON.stringify({
212
- model: this.mapModel(),
213
- messages,
214
- temperature,
215
- max_tokens: maxTokens
216
- })
217
- });
218
- if (!response.ok) {
219
- throw new Error(`OpenRouter API error: ${response.status}`);
220
- }
221
- const data = await response.json();
222
- return data.choices?.[0]?.message?.content || '';
223
- }
224
- async callGemini(messages, temperature, maxTokens) {
225
- const apiKey = this.getApiKey();
226
- if (!apiKey) {
227
- throw new Error('GEMINI_API_KEY not set');
228
- }
229
- const contents = messages
230
- .filter(m => m.role !== 'system')
231
- .map(m => ({
232
- role: m.role === 'assistant' ? 'model' : 'user',
233
- parts: [{ text: m.content }]
234
- }));
235
- const systemInstruction = messages.find(m => m.role === 'system')?.content;
236
- const response = await fetch(`${this.getBaseUrl()}/models/${this.mapModel()}:generateContent?key=${apiKey}`, {
237
- method: 'POST',
238
- headers: {
239
- 'Content-Type': 'application/json'
240
- },
241
- body: JSON.stringify({
242
- contents,
243
- systemInstruction: systemInstruction ? { parts: [{ text: systemInstruction }] } : undefined,
244
- generationConfig: {
245
- temperature,
246
- maxOutputTokens: maxTokens
247
- }
248
- })
249
- });
250
- if (!response.ok) {
251
- throw new Error(`Gemini API error: ${response.status}`);
252
- }
253
- const data = await response.json();
254
- return data.candidates?.[0]?.content?.parts?.[0]?.text || '';
255
- }
256
- async callLocal(messages, temperature) {
257
- return this.callOllama(messages, temperature);
258
- }
259
- buildSystemPrompt(context) {
260
- const envDetails = this.getEnvironmentDetails();
261
- return `You are a friendly AI assistant in a P2P document collaboration network.
262
-
263
- ## User Working Directory
264
- ${context || process.cwd()}
265
-
266
- ## Environment
267
- ${envDetails}`;
268
- }
269
- getEnvironmentDetails() {
270
- return `
271
- ## Available Workflows
272
- - read - Read documents
273
- - summarize - Summarize documents
274
- - improve - Improve documents
275
- - collaborate - Multi-agent collaboration
276
- - query - Query status
277
- - report - Generate reports
278
-
279
- ## System Capabilities
280
- - Document processing (Markdown, Text, PDF, DOCX)
281
- - Multi-agent collaboration (P2P network)
282
- - Workflow engine (constraint layer)
283
- - Quality assessment and auto-send
284
-
285
- ## Current Time
286
- ${new Date().toISOString()}`;
287
- }
288
- buildSummarizePrompt(text, context) {
289
- const maxLength = 8000;
290
- const truncatedText = text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
291
- let prompt = `Please generate a concise and accurate summary for the following document:
292
-
293
- ${truncatedText}
294
-
295
- Please output in the following format:
296
- ## Summary
297
- [Write summary here]
298
-
299
- ## Quality Self-Assessment
300
- [Score 1-10, with reasoning]`;
301
- if (context) {
302
- prompt = `Context: ${context}
303
-
304
- ${prompt}`;
305
- }
306
- return prompt;
307
- }
308
- buildImprovePrompt(content, requirements, context) {
309
- const maxLength = 8000;
310
- const truncatedContent = content.length > maxLength ? content.substring(0, maxLength) + '...' : content;
311
- let prompt = `Please improve the document according to the following requirements:
312
-
313
- Requirements: ${requirements}
314
-
315
- Original Document:
316
- ${truncatedContent}
317
-
318
- Please output only the improved document without additional explanation.`;
319
- if (context) {
320
- prompt = `Context: ${context}
321
-
322
- ${prompt}`;
323
- }
324
- return prompt;
325
- }
326
- estimateQuality(original, summary) {
327
- const coverageRatio = summary.length / Math.max(original.length, 1);
328
- const hasKeyPoints = /\d+\s*[.。]/.test(summary);
329
- const decentLength = summary.length > 100 && summary.length < original.length * 0.5;
330
- let score = 0.5;
331
- if (coverageRatio > 0.1 && coverageRatio < 0.5)
332
- score += 0.2;
333
- if (hasKeyPoints)
334
- score += 0.15;
335
- if (decentLength)
336
- score += 0.15;
337
- return Math.min(1, score);
338
- }
339
- async shouldAutoSend(qualityScore, threshold = 0.7) {
340
- return qualityScore >= threshold;
341
- }
342
- }
343
- let modelInstance = null;
344
- function detectProvider() {
345
- if (process.env.OPENAI_API_KEY)
346
- return 'openai';
347
- if (process.env.ANTHROPIC_API_KEY)
348
- return 'anthropic';
349
- if (process.env.OPENROUTER_API_KEY)
350
- return 'openrouter';
351
- if (process.env.GEMINI_API_KEY)
352
- return 'gemini';
353
- if (process.env.OLLAMA_BASE_URL)
354
- return 'ollama';
355
- if (process.env.MINIMAX_API_KEY)
356
- return 'minimax';
357
- return 'openai';
358
- }
359
- function detectModel(provider) {
360
- const defaults = {
361
- openai: 'gpt-4',
362
- anthropic: 'claude-3-5-sonnet-20241022',
363
- ollama: 'llama3.2',
364
- openrouter: 'anthropic/claude-3.5-sonnet',
365
- gemini: 'gemini-2.0-flash',
366
- minimax: 'MiniMax-M2.7',
367
- local: 'llama3.2'
368
- };
369
- return defaults[provider];
370
- }
371
- export function initPiAI(config = {}) {
372
- const provider = config.provider || detectProvider();
373
- const model = config.model || detectModel(provider);
374
- modelInstance = new PiAIModel({
375
- provider,
376
- apiKey: config.apiKey,
377
- baseUrl: config.baseUrl,
378
- model
379
- });
380
- return modelInstance;
381
- }
382
- export function getModel() {
383
- if (!modelInstance) {
384
- throw new Error('PiAI not initialized. Call initPiAI first.');
385
- }
386
- return modelInstance;
387
- }
388
- export function isModelAvailable() {
389
- return modelInstance !== null;
390
- }
391
- export function getMinimax() {
392
- return getModel();
393
- }
394
- export function initMinimax(config = {}) {
395
- return initPiAI(config);
396
- }
397
- export { PiAIModel as MinimaxLLM };