@bolloon/bolloon-agent 0.1.33 → 0.1.35
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/.auto-evolve-calls +1 -0
- package/.last-auto-evolve-baseline +1 -0
- package/Bolloon.md +103 -0
- package/README.md +7 -2
- package/dist/agents/pi-sdk.js +264 -12
- package/dist/bollharness-integration/index.js +8 -1
- package/dist/bootstrap/bootstrap.js +114 -0
- package/dist/bootstrap/context-collector.js +296 -0
- package/dist/bootstrap/lifecycle-hooks.js +109 -0
- package/dist/bootstrap/project-context.js +151 -0
- package/dist/heartbeat/Watchdog.js +9 -1
- package/dist/index.js +11 -0
- package/dist/llm/pi-ai.js +31 -21
- package/dist/network/p2p-direct.js +59 -2
- package/dist/pi-ecosystem/index.js +9 -6
- package/dist/pi-ecosystem-judgment/adaptive-scan.js +231 -0
- package/dist/pi-ecosystem-judgment/causal-judge.js +449 -0
- package/dist/pi-ecosystem-judgment/decision.js +5 -2
- package/dist/pi-ecosystem-judgment/detect-hook.js +168 -0
- package/dist/pi-ecosystem-judgment/distill-prompt.js +226 -0
- package/dist/pi-ecosystem-judgment/evolve-judgment.js +170 -0
- package/dist/pi-ecosystem-judgment/human-value-pipeline.js +21 -0
- package/dist/pi-ecosystem-judgment/human-value-store.js +283 -22
- package/dist/pi-ecosystem-judgment/injection-gate.js +166 -0
- package/dist/pi-ecosystem-judgment/monitor-gate.js +188 -0
- package/dist/security/builtin-guards.js +124 -0
- package/dist/security/context-router-tool.js +106 -0
- package/dist/security/react-harness.js +143 -0
- package/dist/security/tool-gate.js +235 -0
- package/dist/social/heartbeat.js +19 -2
- package/dist/utils/auto-evolve-policy.js +117 -0
- package/dist/utils/clamp.js +7 -0
- package/dist/utils/double.js +6 -0
- package/dist/web/api-config.html +3 -3
- package/dist/web/client.js +1328 -351
- package/dist/web/index.html +34 -31
- package/dist/web/server.js +1128 -58
- package/dist/web/style.css +370 -0
- package/lefthook.yml +29 -0
- package/package.json +4 -2
- package/scripts/auto-evolve-loop.ts +376 -0
- package/scripts/auto-evolve-oneshot.sh +155 -0
- package/scripts/auto-evolve-snapshot.sh +136 -0
- package/scripts/detect-schema-changes.sh +48 -0
- package/scripts/diff-reviewer.ts +159 -0
- package/scripts/weekly-report.ts +364 -0
- package/src/agents/pi-sdk.ts +293 -15
- package/src/bollharness-integration/index.ts +8 -32
- package/src/bootstrap/bootstrap.ts +132 -0
- package/src/bootstrap/context-collector.ts +342 -0
- package/src/bootstrap/lifecycle-hooks.ts +176 -0
- package/src/bootstrap/project-context.ts +163 -0
- package/src/heartbeat/Watchdog.ts +9 -1
- package/src/index.ts +11 -0
- package/src/llm/pi-ai.ts +33 -22
- package/src/network/p2p-direct.ts +59 -3
- package/src/security/builtin-guards.ts +162 -0
- package/src/security/context-router-tool.ts +122 -0
- package/src/security/react-harness.ts +177 -0
- package/src/security/tool-gate.ts +294 -0
- package/src/social/ant-colony/index.js +19 -0
- package/src/social/heartbeat.ts +18 -2
- package/src/utils/auto-evolve-policy.ts +138 -0
- package/src/utils/clamp.ts +5 -0
- package/src/web/api-config.html +3 -3
- package/src/web/client.js +1328 -351
- package/src/web/index.html +34 -31
- package/src/web/server.ts +1179 -53
- package/src/web/style.css +370 -0
- package/staging/auto-evolve/clean-001/.review-verdict +9 -0
- package/staging/auto-evolve/clean-001/clean-001.patch +14 -0
- package/staging/auto-evolve/e2e-001/.patch-id +1 -0
- package/staging/auto-evolve/e2e-001/.review-verdict +12 -0
- package/staging/auto-evolve/e2e-001/e2e-001.patch +11 -0
- package/staging/auto-evolve/test-bad/.review-verdict +12 -0
- package/staging/auto-evolve/test-bad/test-bad.patch +11 -0
- package/src/social/ant-colony/AdaptiveHeartbeat.ts +0 -131
- package/src/social/ant-colony/PheromoneEngine.ts +0 -302
- package/src/social/ant-colony/index.ts +0 -18
- package/src/social/ant-colony/types.ts +0 -94
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PheromoneEngine - 信息素管理引擎
|
|
3
|
-
*
|
|
4
|
-
* 模拟蚂蚁的信息素系统,用于引导智能体发现和路由决策
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import * as fs from 'fs/promises';
|
|
8
|
-
import * as path from 'path';
|
|
9
|
-
import {
|
|
10
|
-
PheromoneType,
|
|
11
|
-
PheromoneTrail,
|
|
12
|
-
PheromoneField,
|
|
13
|
-
PheromoneDB,
|
|
14
|
-
DEFAULT_PHEROMONE_CONFIG,
|
|
15
|
-
} from './types.js';
|
|
16
|
-
|
|
17
|
-
export { PheromoneType };
|
|
18
|
-
|
|
19
|
-
const PHEROMONE_DB_PATH = path.join(
|
|
20
|
-
process.env.HOME || '/tmp',
|
|
21
|
-
'.bolloon',
|
|
22
|
-
'ant-colony',
|
|
23
|
-
'pheromones.json'
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
export class PheromoneEngine {
|
|
27
|
-
private trails: Map<string, PheromoneTrail> = new Map();
|
|
28
|
-
private fields: Map<string, PheromoneField> = new Map();
|
|
29
|
-
private evaporationTimer: ReturnType<typeof setInterval> | null = null;
|
|
30
|
-
private saveTimer: ReturnType<typeof setInterval> | null = null;
|
|
31
|
-
private dirty: boolean = false;
|
|
32
|
-
|
|
33
|
-
async initialize(): Promise<void> {
|
|
34
|
-
await fs.mkdir(path.dirname(PHEROMONE_DB_PATH), { recursive: true });
|
|
35
|
-
await this.load();
|
|
36
|
-
this.startEvaporation();
|
|
37
|
-
this.startAutoSave();
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
private startEvaporation(): void {
|
|
41
|
-
this.evaporationTimer = setInterval(() => {
|
|
42
|
-
this.evaporate();
|
|
43
|
-
}, DEFAULT_PHEROMONE_CONFIG.evaporationInterval);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
private startAutoSave(): void {
|
|
47
|
-
this.saveTimer = setInterval(() => {
|
|
48
|
-
if (this.dirty) {
|
|
49
|
-
this.save().catch(console.error);
|
|
50
|
-
this.dirty = false;
|
|
51
|
-
}
|
|
52
|
-
}, 30000);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* 放置信息素
|
|
57
|
-
*/
|
|
58
|
-
async deposit(
|
|
59
|
-
type: PheromoneType,
|
|
60
|
-
sourceDid: string,
|
|
61
|
-
targetDid: string,
|
|
62
|
-
strength: number = 0.5,
|
|
63
|
-
options?: {
|
|
64
|
-
capability?: string[];
|
|
65
|
-
qualityScore?: number;
|
|
66
|
-
}
|
|
67
|
-
): Promise<void> {
|
|
68
|
-
const key = this.getTrailKey(type, sourceDid, targetDid);
|
|
69
|
-
const existing = this.trails.get(key);
|
|
70
|
-
|
|
71
|
-
const newStrength = existing
|
|
72
|
-
? Math.min(1, existing.strength + strength * 0.3)
|
|
73
|
-
: Math.min(1, strength);
|
|
74
|
-
|
|
75
|
-
const trail: PheromoneTrail = {
|
|
76
|
-
id: key,
|
|
77
|
-
type,
|
|
78
|
-
sourceDid,
|
|
79
|
-
targetDid,
|
|
80
|
-
strength: newStrength,
|
|
81
|
-
decayRate: DEFAULT_PHEROMONE_CONFIG.decayRate,
|
|
82
|
-
createdAt: existing?.createdAt || Date.now(),
|
|
83
|
-
lastUpdate: Date.now(),
|
|
84
|
-
capability: options?.capability,
|
|
85
|
-
qualityScore: options?.qualityScore,
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
this.trails.set(key, trail);
|
|
89
|
-
this.dirty = true;
|
|
90
|
-
|
|
91
|
-
if (options?.capability) {
|
|
92
|
-
this.updateField(type, targetDid, options.capability);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* 读取某方向的信息素强度
|
|
98
|
-
*/
|
|
99
|
-
getStrength(type: PheromoneType, targetDid: string): number {
|
|
100
|
-
let totalStrength = 0;
|
|
101
|
-
let count = 0;
|
|
102
|
-
|
|
103
|
-
for (const trail of this.trails.values()) {
|
|
104
|
-
if (trail.type === type && trail.targetDid === targetDid) {
|
|
105
|
-
totalStrength += trail.strength;
|
|
106
|
-
count++;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return count > 0 ? totalStrength / count : 0;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* 查询特定能力的最佳节点
|
|
115
|
-
*/
|
|
116
|
-
queryByCapability(capability: string, limit: number = 5): string[] {
|
|
117
|
-
const field = this.fields.get(capability);
|
|
118
|
-
if (!field) return [];
|
|
119
|
-
|
|
120
|
-
const candidates: { did: string; strength: number }[] = [];
|
|
121
|
-
|
|
122
|
-
for (const trail of this.trails.values()) {
|
|
123
|
-
if (
|
|
124
|
-
trail.type === PheromoneType.CAPABILITY &&
|
|
125
|
-
trail.capability?.includes(capability)
|
|
126
|
-
) {
|
|
127
|
-
const score = trail.strength * (trail.qualityScore || 0.5);
|
|
128
|
-
candidates.push({ did: trail.targetDid, strength: score });
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
candidates.sort((a, b) => b.strength - a.strength);
|
|
133
|
-
return candidates.slice(0, limit).map((c) => c.did);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* 获取到达某节点的最佳下一跳
|
|
138
|
-
*/
|
|
139
|
-
getNextHop(targetDid: string, excludeDids: string[] = []): string | null {
|
|
140
|
-
let bestHop: string | null = null;
|
|
141
|
-
let bestStrength = 0;
|
|
142
|
-
|
|
143
|
-
for (const trail of this.trails.values()) {
|
|
144
|
-
if (trail.targetDid === targetDid && trail.strength > bestStrength) {
|
|
145
|
-
if (!excludeDids.includes(trail.sourceDid)) {
|
|
146
|
-
bestHop = trail.sourceDid;
|
|
147
|
-
bestStrength = trail.strength;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return bestHop;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* 获取所有已知节点及其信息素强度
|
|
157
|
-
*/
|
|
158
|
-
getAllNodeStrengths(): Map<string, number> {
|
|
159
|
-
const result = new Map<string, number>();
|
|
160
|
-
|
|
161
|
-
for (const trail of this.trails.values()) {
|
|
162
|
-
const current = result.get(trail.targetDid) || 0;
|
|
163
|
-
result.set(trail.targetDid, Math.max(current, trail.strength));
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return result;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* 获取信息素统计
|
|
171
|
-
*/
|
|
172
|
-
getStats(): {
|
|
173
|
-
totalTrails: number;
|
|
174
|
-
avgStrength: number;
|
|
175
|
-
capabilityCount: number;
|
|
176
|
-
} {
|
|
177
|
-
let totalStrength = 0;
|
|
178
|
-
for (const trail of this.trails.values()) {
|
|
179
|
-
totalStrength += trail.strength;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
return {
|
|
183
|
-
totalTrails: this.trails.size,
|
|
184
|
-
avgStrength: this.trails.size > 0 ? totalStrength / this.trails.size : 0,
|
|
185
|
-
capabilityCount: this.fields.size,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
private getTrailKey(type: PheromoneType, source: string, target: string): string {
|
|
190
|
-
return `${type}:${source}:${target}`;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private updateField(
|
|
194
|
-
type: PheromoneType,
|
|
195
|
-
targetDid: string,
|
|
196
|
-
capability?: string[]
|
|
197
|
-
): void {
|
|
198
|
-
if (!capability) return;
|
|
199
|
-
|
|
200
|
-
for (const cap of capability) {
|
|
201
|
-
let field = this.fields.get(cap);
|
|
202
|
-
if (!field) {
|
|
203
|
-
field = {
|
|
204
|
-
capability: cap,
|
|
205
|
-
avgStrength: 0,
|
|
206
|
-
nodeCount: 0,
|
|
207
|
-
lastUpdate: Date.now(),
|
|
208
|
-
};
|
|
209
|
-
this.fields.set(cap, field);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const trails = Array.from(this.trails.values()).filter(
|
|
213
|
-
(t) => t.type === type && t.capability?.includes(cap)
|
|
214
|
-
);
|
|
215
|
-
|
|
216
|
-
field.avgStrength =
|
|
217
|
-
trails.reduce((sum, t) => sum + t.strength, 0) / (trails.length || 1);
|
|
218
|
-
field.nodeCount = new Set(trails.map((t) => t.targetDid)).size;
|
|
219
|
-
field.lastUpdate = Date.now();
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
private evaporate(): void {
|
|
224
|
-
const now = Date.now();
|
|
225
|
-
const toDelete: string[] = [];
|
|
226
|
-
|
|
227
|
-
for (const [key, trail] of this.trails.entries()) {
|
|
228
|
-
const ageHours = (now - trail.lastUpdate) / (1000 * 60 * 60);
|
|
229
|
-
const decayFactor = Math.pow(1 - trail.decayRate, ageHours);
|
|
230
|
-
trail.strength = trail.strength * decayFactor;
|
|
231
|
-
|
|
232
|
-
if (
|
|
233
|
-
trail.strength < DEFAULT_PHEROMONE_CONFIG.minStrength ||
|
|
234
|
-
now - trail.createdAt > DEFAULT_PHEROMONE_CONFIG.maxTrailAge
|
|
235
|
-
) {
|
|
236
|
-
toDelete.push(key);
|
|
237
|
-
} else {
|
|
238
|
-
trail.lastUpdate = now;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
for (const key of toDelete) {
|
|
243
|
-
this.trails.delete(key);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
if (toDelete.length > 0) {
|
|
247
|
-
this.dirty = true;
|
|
248
|
-
this.save().catch(console.error);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
private async save(): Promise<void> {
|
|
253
|
-
try {
|
|
254
|
-
const data: PheromoneDB = {
|
|
255
|
-
trails: Array.from(this.trails.values()),
|
|
256
|
-
fields: Array.from(this.fields.entries()),
|
|
257
|
-
};
|
|
258
|
-
await fs.writeFile(PHEROMONE_DB_PATH, JSON.stringify(data, null, 2));
|
|
259
|
-
} catch (e) {
|
|
260
|
-
console.warn('[PheromoneEngine] Save failed:', e);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
private async load(): Promise<void> {
|
|
265
|
-
try {
|
|
266
|
-
const data = await fs.readFile(PHEROMONE_DB_PATH, 'utf-8');
|
|
267
|
-
const parsed: PheromoneDB = JSON.parse(data);
|
|
268
|
-
|
|
269
|
-
this.trails.clear();
|
|
270
|
-
for (const t of parsed.trails || []) {
|
|
271
|
-
this.trails.set(t.id, t);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
this.fields.clear();
|
|
275
|
-
for (const [cap, field] of parsed.fields || []) {
|
|
276
|
-
this.fields.set(cap, field);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
console.log(
|
|
280
|
-
`[PheromoneEngine] Loaded ${this.trails.size} trails, ${this.fields.size} fields`
|
|
281
|
-
);
|
|
282
|
-
} catch {
|
|
283
|
-
console.log('[PheromoneEngine] No existing pheromone data, starting fresh');
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
shutdown(): void {
|
|
288
|
-
if (this.evaporationTimer) {
|
|
289
|
-
clearInterval(this.evaporationTimer);
|
|
290
|
-
}
|
|
291
|
-
if (this.saveTimer) {
|
|
292
|
-
clearInterval(this.saveTimer);
|
|
293
|
-
}
|
|
294
|
-
if (this.dirty) {
|
|
295
|
-
this.save()
|
|
296
|
-
.then(() => console.log('[PheromoneEngine] Saved on shutdown'))
|
|
297
|
-
.catch(console.error);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
export const pheromoneEngine = new PheromoneEngine();
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ant Colony Module - 蚁群心跳系统核心模块
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export {
|
|
6
|
-
PheromoneType,
|
|
7
|
-
type PheromoneTrail,
|
|
8
|
-
type PheromoneField,
|
|
9
|
-
type PheromoneDB,
|
|
10
|
-
type AntMessagePayload,
|
|
11
|
-
type HeartbeatDecision,
|
|
12
|
-
type AdaptiveHeartbeatConfig,
|
|
13
|
-
DEFAULT_PHEROMONE_CONFIG,
|
|
14
|
-
DEFAULT_ADAPTIVE_CONFIG,
|
|
15
|
-
} from './types.js';
|
|
16
|
-
|
|
17
|
-
export { PheromoneEngine, pheromoneEngine } from './PheromoneEngine.js';
|
|
18
|
-
export { AdaptiveHeartbeat } from './AdaptiveHeartbeat.js';
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ant Colony Types - 信息素系统类型定义
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export enum PheromoneType {
|
|
6
|
-
DISCOVERY = 'discovery',
|
|
7
|
-
CAPABILITY = 'capability',
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface PheromoneTrail {
|
|
11
|
-
id: string;
|
|
12
|
-
type: PheromoneType;
|
|
13
|
-
sourceDid: string;
|
|
14
|
-
targetDid: string;
|
|
15
|
-
strength: number;
|
|
16
|
-
decayRate: number;
|
|
17
|
-
createdAt: number;
|
|
18
|
-
lastUpdate: number;
|
|
19
|
-
capability?: string[];
|
|
20
|
-
qualityScore?: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface PheromoneField {
|
|
24
|
-
capability: string;
|
|
25
|
-
avgStrength: number;
|
|
26
|
-
nodeCount: number;
|
|
27
|
-
lastUpdate: number;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface PheromoneDB {
|
|
31
|
-
trails: PheromoneTrail[];
|
|
32
|
-
fields: [string, PheromoneField][];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface AntMessagePayload {
|
|
36
|
-
id: string;
|
|
37
|
-
antId: string;
|
|
38
|
-
originDid: string;
|
|
39
|
-
originName: string;
|
|
40
|
-
originPublicKey: string;
|
|
41
|
-
targetCapability: string[];
|
|
42
|
-
ttl: number;
|
|
43
|
-
maxHops: number;
|
|
44
|
-
currentHop: number;
|
|
45
|
-
path: Array<{
|
|
46
|
-
did: string;
|
|
47
|
-
peerId: string;
|
|
48
|
-
timestamp: number;
|
|
49
|
-
}>;
|
|
50
|
-
payload: {
|
|
51
|
-
personaCid?: string;
|
|
52
|
-
ipnsName?: string;
|
|
53
|
-
interests?: string[];
|
|
54
|
-
recommendedBy?: string;
|
|
55
|
-
qualityScore?: number;
|
|
56
|
-
};
|
|
57
|
-
timestamp: number;
|
|
58
|
-
signature: string;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface HeartbeatDecision {
|
|
62
|
-
interval: number;
|
|
63
|
-
shouldExplore: boolean;
|
|
64
|
-
shouldBroadcast: boolean;
|
|
65
|
-
priorityLevel: 'low' | 'normal' | 'high' | 'urgent';
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export interface AdaptiveHeartbeatConfig {
|
|
69
|
-
minInterval: number;
|
|
70
|
-
maxInterval: number;
|
|
71
|
-
baseInterval: number;
|
|
72
|
-
lowActivityThreshold: number;
|
|
73
|
-
highActivityThreshold: number;
|
|
74
|
-
pheromoneBoostFactor: number;
|
|
75
|
-
discoveryBoostFactor: number;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export const DEFAULT_PHEROMONE_CONFIG = {
|
|
79
|
-
decayRate: 0.05,
|
|
80
|
-
evaporationInterval: 5 * 60 * 1000,
|
|
81
|
-
maxTrailAge: 24 * 60 * 60 * 1000,
|
|
82
|
-
minStrength: 0.05,
|
|
83
|
-
maxStrength: 1.0,
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
export const DEFAULT_ADAPTIVE_CONFIG: AdaptiveHeartbeatConfig = {
|
|
87
|
-
minInterval: 10 * 1000,
|
|
88
|
-
maxInterval: 120 * 1000,
|
|
89
|
-
baseInterval: 30 * 1000,
|
|
90
|
-
lowActivityThreshold: 0.5,
|
|
91
|
-
highActivityThreshold: 5,
|
|
92
|
-
pheromoneBoostFactor: 0.3,
|
|
93
|
-
discoveryBoostFactor: 0.4,
|
|
94
|
-
};
|