@bolloon/bolloon-agent 0.1.38 → 0.1.40
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/dist/agents/constraint-layer.js +1 -2
- package/dist/llm/system-prompt/layers/channel/local.md +14 -0
- package/dist/llm/system-prompt/layers/channel/p2p-agent.md +18 -0
- package/dist/llm/system-prompt/layers/channel/p2p-visitor.md +19 -0
- package/dist/llm/system-prompt/layers/core/artifacts_storage.md +89 -0
- package/dist/llm/system-prompt/layers/core/evenhandedness.md +21 -0
- package/dist/llm/system-prompt/layers/core/hibs_reminders.md +15 -0
- package/dist/llm/system-prompt/layers/core/identity.md +37 -0
- package/dist/llm/system-prompt/layers/core/knowledge.md +17 -0
- package/dist/llm/system-prompt/layers/core/memory_system.md +12 -0
- package/dist/llm/system-prompt/layers/core/network_filesystem.md +28 -0
- package/dist/llm/system-prompt/layers/core/refusal.md +37 -0
- package/dist/llm/system-prompt/layers/core/tone.md +31 -0
- package/dist/llm/system-prompt/layers/core/tools.thin.md +13 -0
- package/dist/llm/system-prompt/layers/core/wellbeing.md +41 -0
- package/dist/llm/system-prompt/layers/role/architect.md +20 -0
- package/dist/llm/system-prompt/layers/role/expert.md +19 -0
- package/dist/llm/system-prompt/layers/role/implementer.md +15 -0
- package/dist/llm/system-prompt/layers/role/security.md +15 -0
- package/dist/llm/system-prompt/layers/tool/artifacts.md +72 -0
- package/dist/llm/system-prompt/layers/tool/bash.md +25 -0
- package/dist/llm/system-prompt/layers/tool/hibs_api.md +171 -0
- package/dist/llm/system-prompt/layers/tool/image_search.md +70 -0
- package/dist/llm/system-prompt/layers/tool/manifest.md +89 -0
- package/dist/llm/system-prompt/layers/tool/mcp_apps.md +53 -0
- package/dist/llm/system-prompt/layers/tool/web_search.md +83 -0
- package/dist/llm/system-prompt/registry.js +5 -1
- package/dist/web/client.js +28 -1
- package/dist/web/server.js +37 -5
- package/dist/web/ui/message-renderer.js +9 -0
- package/package.json +1 -1
- package/dist/bollharness-integration/llm/pi-ai.js +0 -397
- package/dist/bollharness-integration/pi-ecosystem-colony/index.js +0 -365
- package/dist/bollharness-integration/pi-ecosystem-goals/index.js +0 -458
- package/dist/bollharness-integration/pi-ecosystem-judgment/decision.js +0 -300
- package/dist/bollharness-integration/pi-ecosystem-judgment/distillation.js +0 -291
- package/dist/bollharness-integration/pi-ecosystem-judgment/index.js +0 -445
- package/dist/bollharness-integration/pi-ecosystem-mcp/index.js +0 -331
- package/dist/bollharness-integration/pi-ecosystem-subagents/index.js +0 -303
- package/dist/constraints/commands.js +0 -100
- package/dist/constraints/permissions.js +0 -37
- package/dist/constraints/runtime.js +0 -135
- package/dist/constraints/session.js +0 -48
- package/dist/constraints/system-init.js +0 -51
- package/dist/constraints/tools.js +0 -104
- package/dist/llm/minimax-provider.js +0 -46
- package/dist/llm/minimax.js +0 -45
- package/dist/pi-ecosystem-colony/index.js +0 -365
- package/dist/runtime/context/minimax-prompt.js +0 -178
- package/dist/runtime/context/sys-prompt.js +0 -1
- package/dist/social/ant-colony/AdaptiveHeartbeat.js +0 -101
- package/dist/social/ant-colony/PheromoneEngine.js +0 -227
- package/dist/social/ant-colony/index.js +0 -6
- package/dist/social/ant-colony/types.js +0 -24
- package/dist/utils/double.js +0 -6
|
@@ -1,365 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pi Ant Colony Integration for Bolloon
|
|
3
|
-
*
|
|
4
|
-
* Multi-agent collaboration system with white-box signal protocol.
|
|
5
|
-
* Based on oh-pi's ant colony system: COLONY_SIGNAL protocol for agent coordination.
|
|
6
|
-
*
|
|
7
|
-
* Signal Protocol:
|
|
8
|
-
* COLONY_SIGNAL:LAUNCHED → SCOUTING → WORKING → REVIEWING → COMPLETE
|
|
9
|
-
*
|
|
10
|
-
* Key features:
|
|
11
|
-
* - Fully visible signal protocol (no black boxes)
|
|
12
|
-
* - Per-ant turn limits, cost tracking, concurrent scheduling
|
|
13
|
-
* - White-box design: no "what is it doing in the background" anxiety
|
|
14
|
-
*/
|
|
15
|
-
import { EventEmitter } from 'events';
|
|
16
|
-
import * as fs from 'fs/promises';
|
|
17
|
-
import * as path from 'path';
|
|
18
|
-
// Colony state
|
|
19
|
-
const ants = new Map();
|
|
20
|
-
const tasks = new Map();
|
|
21
|
-
const signalHistory = [];
|
|
22
|
-
const STATE_DIR = path.join(process.env.HOME || '/tmp', '.bolloon', 'colony');
|
|
23
|
-
// Event emitter
|
|
24
|
-
class ColonyEventEmitter extends EventEmitter {
|
|
25
|
-
}
|
|
26
|
-
const colonyEvents = new ColonyEventEmitter();
|
|
27
|
-
/**
|
|
28
|
-
* Generate a unique ant ID
|
|
29
|
-
*/
|
|
30
|
-
function generateAntId() {
|
|
31
|
-
return `ant-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Register a new ant in the colony
|
|
35
|
-
*/
|
|
36
|
-
export function registerAnt(name, role, maxTurns = 10, tokenBudget = 50000) {
|
|
37
|
-
const id = generateAntId();
|
|
38
|
-
const ant = {
|
|
39
|
-
id,
|
|
40
|
-
name,
|
|
41
|
-
role,
|
|
42
|
-
signal: 'LAUNCHED',
|
|
43
|
-
turnCount: 0,
|
|
44
|
-
maxTurns,
|
|
45
|
-
tokenBudget,
|
|
46
|
-
tokensUsed: 0,
|
|
47
|
-
createdAt: new Date().toISOString(),
|
|
48
|
-
updatedAt: new Date().toISOString(),
|
|
49
|
-
};
|
|
50
|
-
ants.set(id, ant);
|
|
51
|
-
emitSignal(id, 'LAUNCHED');
|
|
52
|
-
console.log(`[Colony] Registered ant: ${name} (${role})`);
|
|
53
|
-
return ant;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Emit a signal transition
|
|
57
|
-
*/
|
|
58
|
-
function emitSignal(antId, newSignal, details) {
|
|
59
|
-
const ant = ants.get(antId);
|
|
60
|
-
if (!ant)
|
|
61
|
-
return;
|
|
62
|
-
const event = {
|
|
63
|
-
antId,
|
|
64
|
-
antName: ant.name,
|
|
65
|
-
fromSignal: ant.signal,
|
|
66
|
-
toSignal: newSignal,
|
|
67
|
-
timestamp: new Date().toISOString(),
|
|
68
|
-
details,
|
|
69
|
-
};
|
|
70
|
-
signalHistory.push(event);
|
|
71
|
-
if (signalHistory.length > 100) {
|
|
72
|
-
signalHistory.shift();
|
|
73
|
-
}
|
|
74
|
-
ant.signal = newSignal;
|
|
75
|
-
ant.updatedAt = new Date().toISOString();
|
|
76
|
-
ants.set(antId, ant);
|
|
77
|
-
colonyEvents.emit('signal', event);
|
|
78
|
-
console.log(`[Colony] ${ant.name}: ${event.fromSignal} → ${event.toSignal}${details ? ` (${details})` : ''}`);
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Transition ant to SCOUTING
|
|
82
|
-
*/
|
|
83
|
-
export function antScouting(antId, task) {
|
|
84
|
-
const ant = ants.get(antId);
|
|
85
|
-
if (!ant)
|
|
86
|
-
return;
|
|
87
|
-
ant.task = task;
|
|
88
|
-
ants.set(antId, ant);
|
|
89
|
-
emitSignal(antId, 'SCOUTING', `Task: ${task.substring(0, 50)}...`);
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Transition ant to WORKING
|
|
93
|
-
*/
|
|
94
|
-
export function antWorking(antId) {
|
|
95
|
-
const ant = ants.get(antId);
|
|
96
|
-
if (!ant)
|
|
97
|
-
return;
|
|
98
|
-
emitSignal(antId, 'WORKING');
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Transition ant to REVIEWING
|
|
102
|
-
*/
|
|
103
|
-
export function antReviewing(antId) {
|
|
104
|
-
emitSignal(antId, 'REVIEWING');
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Complete ant work
|
|
108
|
-
*/
|
|
109
|
-
export function antComplete(antId, result) {
|
|
110
|
-
const ant = ants.get(antId);
|
|
111
|
-
if (!ant)
|
|
112
|
-
return;
|
|
113
|
-
ant.result = result;
|
|
114
|
-
ants.set(antId, ant);
|
|
115
|
-
emitSignal(antId, 'COMPLETE', `Result: ${result.substring(0, 50)}...`);
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Fail ant work
|
|
119
|
-
*/
|
|
120
|
-
export function antFail(antId, error) {
|
|
121
|
-
const ant = ants.get(antId);
|
|
122
|
-
if (!ant)
|
|
123
|
-
return;
|
|
124
|
-
ant.result = error;
|
|
125
|
-
ants.set(antId, ant);
|
|
126
|
-
emitSignal(antId, 'FAILED', error);
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Abort ant work
|
|
130
|
-
*/
|
|
131
|
-
export function antAbort(antId, reason) {
|
|
132
|
-
emitSignal(antId, 'ABORTED', reason);
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Increment turn count
|
|
136
|
-
*/
|
|
137
|
-
export function antTick(antId, tokensUsed = 0) {
|
|
138
|
-
const ant = ants.get(antId);
|
|
139
|
-
if (!ant)
|
|
140
|
-
return;
|
|
141
|
-
ant.turnCount++;
|
|
142
|
-
ant.tokensUsed += tokensUsed;
|
|
143
|
-
ant.updatedAt = new Date().toISOString();
|
|
144
|
-
ants.set(antId, ant);
|
|
145
|
-
// Check if exceeded limits
|
|
146
|
-
if (ant.turnCount >= ant.maxTurns) {
|
|
147
|
-
antAbort(antId, 'Max turns exceeded');
|
|
148
|
-
}
|
|
149
|
-
else if (ant.tokensUsed >= ant.tokenBudget) {
|
|
150
|
-
antAbort(antId, 'Token budget exceeded');
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Create a colony task
|
|
155
|
-
*/
|
|
156
|
-
export function createTask(description) {
|
|
157
|
-
const id = `task-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;
|
|
158
|
-
const task = {
|
|
159
|
-
id,
|
|
160
|
-
description,
|
|
161
|
-
status: 'pending',
|
|
162
|
-
assignedAnts: [],
|
|
163
|
-
results: new Map(),
|
|
164
|
-
createdAt: new Date().toISOString(),
|
|
165
|
-
};
|
|
166
|
-
tasks.set(id, task);
|
|
167
|
-
console.log(`[Colony] Created task: ${id} - ${description.substring(0, 50)}...`);
|
|
168
|
-
return task;
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Dispatch task to ants
|
|
172
|
-
*/
|
|
173
|
-
export function dispatchTask(taskId, antIds) {
|
|
174
|
-
const task = tasks.get(taskId);
|
|
175
|
-
if (!task)
|
|
176
|
-
return;
|
|
177
|
-
task.status = 'dispatched';
|
|
178
|
-
task.assignedAnts = antIds;
|
|
179
|
-
tasks.set(taskId, task);
|
|
180
|
-
for (const antId of antIds) {
|
|
181
|
-
const ant = ants.get(antId);
|
|
182
|
-
if (ant) {
|
|
183
|
-
antScouting(antId, task.description);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
console.log(`[Colony] Dispatched task ${taskId} to ${antIds.length} ants`);
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Record ant result for a task
|
|
190
|
-
*/
|
|
191
|
-
export function recordResult(taskId, antId, result) {
|
|
192
|
-
const task = tasks.get(taskId);
|
|
193
|
-
if (!task)
|
|
194
|
-
return;
|
|
195
|
-
task.results.set(antId, result);
|
|
196
|
-
// Check if all ants completed
|
|
197
|
-
if (task.results.size === task.assignedAnts.length) {
|
|
198
|
-
task.status = 'completed';
|
|
199
|
-
task.completedAt = new Date().toISOString();
|
|
200
|
-
for (const id of task.assignedAnts) {
|
|
201
|
-
antReviewing(id);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
tasks.set(taskId, task);
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Get ant by ID
|
|
208
|
-
*/
|
|
209
|
-
export function getAnt(antId) {
|
|
210
|
-
return ants.get(antId);
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* List all ants
|
|
214
|
-
*/
|
|
215
|
-
export function listAnts() {
|
|
216
|
-
return Array.from(ants.values());
|
|
217
|
-
}
|
|
218
|
-
/**
|
|
219
|
-
* List ants by role
|
|
220
|
-
*/
|
|
221
|
-
export function listAntsByRole(role) {
|
|
222
|
-
return Array.from(ants.values()).filter((a) => a.role === role);
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Get ants by signal state
|
|
226
|
-
*/
|
|
227
|
-
export function listAntsBySignal(signal) {
|
|
228
|
-
return Array.from(ants.values()).filter((a) => a.signal === signal);
|
|
229
|
-
}
|
|
230
|
-
/**
|
|
231
|
-
* Get active ants (not complete/failed/aborted)
|
|
232
|
-
*/
|
|
233
|
-
export function getActiveAnts() {
|
|
234
|
-
return Array.from(ants.values()).filter((a) => !['COMPLETE', 'FAILED', 'ABORTED'].includes(a.signal));
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Get task by ID
|
|
238
|
-
*/
|
|
239
|
-
export function getTask(taskId) {
|
|
240
|
-
return tasks.get(taskId);
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* List all tasks
|
|
244
|
-
*/
|
|
245
|
-
export function listTasks() {
|
|
246
|
-
return Array.from(tasks.values());
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* Get signal history
|
|
250
|
-
*/
|
|
251
|
-
export function getSignalHistory() {
|
|
252
|
-
return [...signalHistory];
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Get colony status
|
|
256
|
-
*/
|
|
257
|
-
export function getColonyStatus() {
|
|
258
|
-
const antList = Array.from(ants.values());
|
|
259
|
-
const taskList = Array.from(tasks.values());
|
|
260
|
-
const signalDistribution = {
|
|
261
|
-
LAUNCHED: 0,
|
|
262
|
-
SCOUTING: 0,
|
|
263
|
-
WORKING: 0,
|
|
264
|
-
REVIEWING: 0,
|
|
265
|
-
COMPLETE: 0,
|
|
266
|
-
FAILED: 0,
|
|
267
|
-
ABORTED: 0,
|
|
268
|
-
};
|
|
269
|
-
for (const ant of antList) {
|
|
270
|
-
signalDistribution[ant.signal]++;
|
|
271
|
-
}
|
|
272
|
-
return {
|
|
273
|
-
antCount: antList.length,
|
|
274
|
-
activeAnts: antList.filter((a) => !['COMPLETE', 'FAILED', 'ABORTED'].includes(a.signal)).length,
|
|
275
|
-
taskCount: taskList.length,
|
|
276
|
-
activeTasks: taskList.filter((t) => t.status === 'in_progress' || t.status === 'dispatched').length,
|
|
277
|
-
signalDistribution,
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Subscribe to colony events
|
|
282
|
-
*/
|
|
283
|
-
export function onColonyEvent(event, callback) {
|
|
284
|
-
colonyEvents.on(event, callback);
|
|
285
|
-
}
|
|
286
|
-
/**
|
|
287
|
-
* Unsubscribe from colony events
|
|
288
|
-
*/
|
|
289
|
-
export function offColonyEvent(event, callback) {
|
|
290
|
-
colonyEvents.off(event, callback);
|
|
291
|
-
}
|
|
292
|
-
/**
|
|
293
|
-
* Get formatted colony dump for debugging
|
|
294
|
-
*/
|
|
295
|
-
export function getColonyDump() {
|
|
296
|
-
const status = getColonyStatus();
|
|
297
|
-
const active = getActiveAnts();
|
|
298
|
-
let dump = '# Colony Status\n\n';
|
|
299
|
-
dump += `Ants: ${status.antCount} total, ${status.activeAnts} active\n`;
|
|
300
|
-
dump += `Tasks: ${status.taskCount} total, ${status.activeTasks} active\n\n`;
|
|
301
|
-
dump += '## Signal Distribution\n';
|
|
302
|
-
for (const [signal, count] of Object.entries(status.signalDistribution)) {
|
|
303
|
-
if (count > 0) {
|
|
304
|
-
dump += `- ${signal}: ${count}\n`;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
dump += '\n## Active Ants\n';
|
|
308
|
-
for (const ant of active) {
|
|
309
|
-
dump += `- ${ant.name} (${ant.role}): ${ant.signal} [${ant.turnCount}/${ant.maxTurns} turns, ${ant.tokensUsed}/${ant.tokenBudget} tokens]\n`;
|
|
310
|
-
if (ant.task) {
|
|
311
|
-
dump += ` Task: ${ant.task.substring(0, 60)}...\n`;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
dump += '\n## Recent Signals\n';
|
|
315
|
-
const recent = signalHistory.slice(-10);
|
|
316
|
-
for (const event of recent.reverse()) {
|
|
317
|
-
dump += `- ${event.timestamp}: ${event.antName}: ${event.fromSignal} → ${event.toSignal}\n`;
|
|
318
|
-
}
|
|
319
|
-
return dump;
|
|
320
|
-
}
|
|
321
|
-
/**
|
|
322
|
-
* Persist colony state
|
|
323
|
-
*/
|
|
324
|
-
export async function persistColony() {
|
|
325
|
-
try {
|
|
326
|
-
await fs.mkdir(STATE_DIR, { recursive: true });
|
|
327
|
-
const state = {
|
|
328
|
-
ants: Array.from(ants.values()),
|
|
329
|
-
tasks: Array.from(tasks.entries()).map(([id, t]) => ({
|
|
330
|
-
...t,
|
|
331
|
-
results: Array.from(t.results.entries()),
|
|
332
|
-
})),
|
|
333
|
-
signalHistory: signalHistory.slice(-50),
|
|
334
|
-
persistedAt: new Date().toISOString(),
|
|
335
|
-
};
|
|
336
|
-
await fs.writeFile(path.join(STATE_DIR, 'colony.json'), JSON.stringify(state, null, 2));
|
|
337
|
-
console.log('[Colony] Persisted state');
|
|
338
|
-
}
|
|
339
|
-
catch (e) {
|
|
340
|
-
console.warn('[Colony] Failed to persist:', e);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
/**
|
|
344
|
-
* Load colony state
|
|
345
|
-
*/
|
|
346
|
-
export async function loadColony() {
|
|
347
|
-
try {
|
|
348
|
-
const data = await fs.readFile(path.join(STATE_DIR, 'colony.json'), 'utf-8');
|
|
349
|
-
const state = JSON.parse(data);
|
|
350
|
-
ants.clear();
|
|
351
|
-
for (const a of state.ants) {
|
|
352
|
-
ants.set(a.id, a);
|
|
353
|
-
}
|
|
354
|
-
tasks.clear();
|
|
355
|
-
for (const t of state.tasks) {
|
|
356
|
-
tasks.set(t.id, { ...t, results: new Map(t.results) });
|
|
357
|
-
}
|
|
358
|
-
signalHistory.length = 0;
|
|
359
|
-
signalHistory.push(...state.signalHistory);
|
|
360
|
-
console.log(`[Colony] Loaded ${ants.size} ants, ${tasks.size} tasks`);
|
|
361
|
-
}
|
|
362
|
-
catch {
|
|
363
|
-
// No persisted state
|
|
364
|
-
}
|
|
365
|
-
}
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import { initMinimaxProvider } from '../../llm/minimax-provider.js';
|
|
2
|
-
export class MinimaxLLM {
|
|
3
|
-
provider;
|
|
4
|
-
model;
|
|
5
|
-
constructor(config, provider) {
|
|
6
|
-
this.provider = provider;
|
|
7
|
-
this.model = config.model || 'MiniMax-M2.7';
|
|
8
|
-
}
|
|
9
|
-
buildSystemPrompt(context) {
|
|
10
|
-
const envDetails = this.getEnvironmentDetails();
|
|
11
|
-
return `你是一个友好的AI助手,正在与用户对话。
|
|
12
|
-
|
|
13
|
-
## 用户工作目录
|
|
14
|
-
${context || process.cwd()}
|
|
15
|
-
|
|
16
|
-
## 环境信息
|
|
17
|
-
${envDetails}`;
|
|
18
|
-
}
|
|
19
|
-
getEnvironmentDetails() {
|
|
20
|
-
const workflows = [
|
|
21
|
-
'read - 读取文档',
|
|
22
|
-
'summarize - 总结文档',
|
|
23
|
-
'improve - 改进文档',
|
|
24
|
-
'collaborate - 多智能体协作',
|
|
25
|
-
'query - 查询状态',
|
|
26
|
-
'report - 生成报告'
|
|
27
|
-
];
|
|
28
|
-
const capabilities = [
|
|
29
|
-
'文档处理 (Markdown, Text, PDF, DOCX)',
|
|
30
|
-
'多智能体协作 (P2P 网络)',
|
|
31
|
-
'工作流引擎 (约束层检查)',
|
|
32
|
-
'质量评估与自动发送'
|
|
33
|
-
];
|
|
34
|
-
return `
|
|
35
|
-
## 可用工作流
|
|
36
|
-
${workflows.map(w => `- ${w}`).join('\n')}
|
|
37
|
-
|
|
38
|
-
## 系统能力
|
|
39
|
-
${capabilities.map(c => `- ${c}`).join('\n')}
|
|
40
|
-
|
|
41
|
-
## 当前时间
|
|
42
|
-
${new Date().toISOString()}`;
|
|
43
|
-
}
|
|
44
|
-
async chat(message, context) {
|
|
45
|
-
const systemPrompt = this.buildSystemPrompt(context);
|
|
46
|
-
try {
|
|
47
|
-
const data = await this.provider.chat({
|
|
48
|
-
model: this.model,
|
|
49
|
-
messages: [
|
|
50
|
-
{ role: 'system', content: systemPrompt },
|
|
51
|
-
{ role: 'user', content: message, sender_name: 'user', sender_type: 'USER' }
|
|
52
|
-
],
|
|
53
|
-
temperature: 0.8
|
|
54
|
-
});
|
|
55
|
-
if (data.base_resp?.status_msg) {
|
|
56
|
-
console.error('Minimax API error:', data.base_resp.status_msg);
|
|
57
|
-
return { reply: `AI服务暂时不可用: ${data.base_resp.status_msg}` };
|
|
58
|
-
}
|
|
59
|
-
const reply = data.choices?.[0]?.message?.content || '抱歉,我没有收到回复。';
|
|
60
|
-
return { reply };
|
|
61
|
-
}
|
|
62
|
-
catch (error) {
|
|
63
|
-
console.error('Minimax chat error:', error);
|
|
64
|
-
return { reply: '抱歉,AI服务暂时不可用。' };
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
async summarize(text, context) {
|
|
68
|
-
const prompt = this.buildSummarizePrompt(text, context);
|
|
69
|
-
try {
|
|
70
|
-
const data = await this.provider.chat({
|
|
71
|
-
model: this.model,
|
|
72
|
-
messages: [
|
|
73
|
-
{ role: 'system', content: 'You are a professional document summarizer.' },
|
|
74
|
-
{ role: 'user', content: prompt, sender_name: 'user', sender_type: 'USER' }
|
|
75
|
-
],
|
|
76
|
-
temperature: 0.7
|
|
77
|
-
});
|
|
78
|
-
if (data.base_resp?.status_msg) {
|
|
79
|
-
console.error('Minimax API error:', data.base_resp.status_msg);
|
|
80
|
-
return { summary: `API错误: ${data.base_resp.status_msg}`, qualityScore: 0 };
|
|
81
|
-
}
|
|
82
|
-
const content = data.choices?.[0]?.message?.content || '';
|
|
83
|
-
const qualityScore = this.estimateQuality(text, content);
|
|
84
|
-
return { summary: content, qualityScore };
|
|
85
|
-
}
|
|
86
|
-
catch (error) {
|
|
87
|
-
console.error('Minimax API error:', error);
|
|
88
|
-
return {
|
|
89
|
-
summary: text.substring(0, 500) + '...',
|
|
90
|
-
qualityScore: 0.5
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
buildSummarizePrompt(text, context) {
|
|
95
|
-
const maxLength = 8000;
|
|
96
|
-
const truncatedText = text.length > maxLength ? text.substring(0, maxLength) + '...' : text;
|
|
97
|
-
let prompt = `请为以下文档生成简洁准确的摘要:
|
|
98
|
-
|
|
99
|
-
${truncatedText}
|
|
100
|
-
|
|
101
|
-
请按以下格式输出:
|
|
102
|
-
## 摘要
|
|
103
|
-
[在此处撰写摘要]
|
|
104
|
-
|
|
105
|
-
## 质量自评
|
|
106
|
-
[评分 1-10,说明理由]`;
|
|
107
|
-
if (context) {
|
|
108
|
-
prompt = `背景信息:${context}
|
|
109
|
-
|
|
110
|
-
${prompt}`;
|
|
111
|
-
}
|
|
112
|
-
return prompt;
|
|
113
|
-
}
|
|
114
|
-
estimateQuality(original, summary) {
|
|
115
|
-
const coverageRatio = summary.length / Math.max(original.length, 1);
|
|
116
|
-
const hasKeyPoints = /\d+\s*[.。]/.test(summary);
|
|
117
|
-
const decentLength = summary.length > 100 && summary.length < original.length * 0.5;
|
|
118
|
-
let score = 0.5;
|
|
119
|
-
if (coverageRatio > 0.1 && coverageRatio < 0.5)
|
|
120
|
-
score += 0.2;
|
|
121
|
-
if (hasKeyPoints)
|
|
122
|
-
score += 0.15;
|
|
123
|
-
if (decentLength)
|
|
124
|
-
score += 0.15;
|
|
125
|
-
return Math.min(1, score);
|
|
126
|
-
}
|
|
127
|
-
async improveContent(content, requirements, context) {
|
|
128
|
-
const prompt = this.buildImprovePrompt(content, requirements, context);
|
|
129
|
-
try {
|
|
130
|
-
const data = await this.provider.chatPro({
|
|
131
|
-
model: this.model,
|
|
132
|
-
messages: [
|
|
133
|
-
{ role: 'system', content: 'You are a professional document editor and improver.' },
|
|
134
|
-
{ role: 'user', content: prompt }
|
|
135
|
-
],
|
|
136
|
-
temperature: 0.8
|
|
137
|
-
});
|
|
138
|
-
return data.choices?.[0]?.message?.content || content;
|
|
139
|
-
}
|
|
140
|
-
catch (error) {
|
|
141
|
-
console.error('Minimax improve error:', error);
|
|
142
|
-
return content;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
buildImprovePrompt(content, requirements, context) {
|
|
146
|
-
const maxLength = 8000;
|
|
147
|
-
const truncatedContent = content.length > maxLength ? content.substring(0, maxLength) + '...' : content;
|
|
148
|
-
let prompt = `请根据以下要求改进文档:
|
|
149
|
-
|
|
150
|
-
要求:${requirements}
|
|
151
|
-
|
|
152
|
-
原始文档:
|
|
153
|
-
${truncatedContent}
|
|
154
|
-
|
|
155
|
-
请直接输出改进后的文档,不要添加额外说明。`;
|
|
156
|
-
if (context) {
|
|
157
|
-
prompt = `背景信息:${context}
|
|
158
|
-
|
|
159
|
-
${prompt}`;
|
|
160
|
-
}
|
|
161
|
-
return prompt;
|
|
162
|
-
}
|
|
163
|
-
async shouldAutoSend(qualityScore, threshold = 0.7) {
|
|
164
|
-
return qualityScore >= threshold;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
let minimaxInstance = null;
|
|
168
|
-
export function initMinimax(config) {
|
|
169
|
-
const provider = initMinimaxProvider(config.apiKey);
|
|
170
|
-
minimaxInstance = new MinimaxLLM(config, provider);
|
|
171
|
-
return minimaxInstance;
|
|
172
|
-
}
|
|
173
|
-
export function getMinimax() {
|
|
174
|
-
if (!minimaxInstance) {
|
|
175
|
-
throw new Error('Minimax not initialized. Call initMinimax first.');
|
|
176
|
-
}
|
|
177
|
-
return minimaxInstance;
|
|
178
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { PiAIModel as MinimaxLLM, initPiAI, getModel, isModelAvailable, getMinimax, initMinimax } from '../../llm/pi-ai.js';
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AdaptiveHeartbeat - 动态心跳策略
|
|
3
|
-
*
|
|
4
|
-
* 基于活跃度、信息素密度等因子动态调整心跳间隔
|
|
5
|
-
*/
|
|
6
|
-
import { DEFAULT_ADAPTIVE_CONFIG, } from './types.js';
|
|
7
|
-
export class AdaptiveHeartbeat {
|
|
8
|
-
config;
|
|
9
|
-
lastActivityTime = Date.now();
|
|
10
|
-
activityHistory = [];
|
|
11
|
-
recentDiscoveries = 0;
|
|
12
|
-
pheromoneDensity = 0;
|
|
13
|
-
discoveryBoost = 0;
|
|
14
|
-
activityTimer = null;
|
|
15
|
-
constructor(config) {
|
|
16
|
-
this.config = { ...DEFAULT_ADAPTIVE_CONFIG, ...config };
|
|
17
|
-
this.startActivityTracking();
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* 获取下一次心跳的决策
|
|
21
|
-
*/
|
|
22
|
-
decide() {
|
|
23
|
-
const now = Date.now();
|
|
24
|
-
const timeSinceLastActivity = now - this.lastActivityTime;
|
|
25
|
-
const activityRate = this.calculateActivityRate();
|
|
26
|
-
const pheromoneFactor = this.pheromoneDensity;
|
|
27
|
-
const discoveryFactor = this.calculateDiscoveryFactor();
|
|
28
|
-
const combinedFactor = activityRate * 0.2 +
|
|
29
|
-
pheromoneFactor * this.config.pheromoneBoostFactor +
|
|
30
|
-
discoveryFactor * this.config.discoveryBoostFactor;
|
|
31
|
-
const interval = Math.max(this.config.minInterval, Math.min(this.config.maxInterval, this.config.baseInterval * (1 - combinedFactor * 0.7)));
|
|
32
|
-
let priority = 'normal';
|
|
33
|
-
if (discoveryFactor > 0.5 || this.discoveryBoost > 0.6) {
|
|
34
|
-
priority = 'high';
|
|
35
|
-
}
|
|
36
|
-
else if (this.discoveryBoost > 0.8) {
|
|
37
|
-
priority = 'urgent';
|
|
38
|
-
}
|
|
39
|
-
else if (activityRate < this.config.lowActivityThreshold) {
|
|
40
|
-
priority = 'low';
|
|
41
|
-
}
|
|
42
|
-
return {
|
|
43
|
-
interval: Math.round(interval),
|
|
44
|
-
shouldExplore: discoveryFactor > 0.3 || pheromoneFactor > 0.5,
|
|
45
|
-
shouldBroadcast: priority !== 'low' || timeSinceLastActivity > this.config.baseInterval,
|
|
46
|
-
priorityLevel: priority,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* 记录活跃事件
|
|
51
|
-
*/
|
|
52
|
-
recordActivity(type) {
|
|
53
|
-
const now = Date.now();
|
|
54
|
-
this.lastActivityTime = now;
|
|
55
|
-
this.activityHistory.push(now);
|
|
56
|
-
if (type === 'discovery') {
|
|
57
|
-
this.recentDiscoveries++;
|
|
58
|
-
this.discoveryBoost = Math.min(1, this.discoveryBoost + 0.2);
|
|
59
|
-
}
|
|
60
|
-
this.discoveryBoost = Math.max(0, this.discoveryBoost - 0.05);
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* 设置信息素密度
|
|
64
|
-
*/
|
|
65
|
-
setPheromoneDensity(density) {
|
|
66
|
-
this.pheromoneDensity = Math.max(0, Math.min(1, density));
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* 获取当前配置
|
|
70
|
-
*/
|
|
71
|
-
getConfig() {
|
|
72
|
-
return { ...this.config };
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* 更新配置
|
|
76
|
-
*/
|
|
77
|
-
updateConfig(updates) {
|
|
78
|
-
this.config = { ...this.config, ...updates };
|
|
79
|
-
}
|
|
80
|
-
calculateActivityRate() {
|
|
81
|
-
const now = Date.now();
|
|
82
|
-
const recentActivity = this.activityHistory.filter((t) => now - t < 60000).length;
|
|
83
|
-
return recentActivity / 60;
|
|
84
|
-
}
|
|
85
|
-
calculateDiscoveryFactor() {
|
|
86
|
-
return Math.min(1, this.recentDiscoveries / 5);
|
|
87
|
-
}
|
|
88
|
-
startActivityTracking() {
|
|
89
|
-
this.activityTimer = setInterval(() => {
|
|
90
|
-
const cutoff = Date.now() - 5 * 60 * 1000;
|
|
91
|
-
this.activityHistory = this.activityHistory.filter((t) => t > cutoff);
|
|
92
|
-
this.recentDiscoveries = Math.max(0, this.recentDiscoveries - 1);
|
|
93
|
-
this.discoveryBoost = Math.max(0, this.discoveryBoost - 0.1);
|
|
94
|
-
}, 60000);
|
|
95
|
-
}
|
|
96
|
-
shutdown() {
|
|
97
|
-
if (this.activityTimer) {
|
|
98
|
-
clearInterval(this.activityTimer);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|