oh-pi 0.1.59 → 0.1.60
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/package.json
CHANGED
|
@@ -159,7 +159,7 @@ interface WaveOptions {
|
|
|
159
159
|
/**
|
|
160
160
|
* 并发执行一批蚂蚁,自适应调节并发度
|
|
161
161
|
*/
|
|
162
|
-
async function runAntWave(opts: WaveOptions): Promise<"ok"> {
|
|
162
|
+
async function runAntWave(opts: WaveOptions): Promise<"ok" | "budget"> {
|
|
163
163
|
const { nest, cwd, caste, signal, callbacks, currentModel } = opts;
|
|
164
164
|
const casteModel = opts.modelOverrides?.[caste] || currentModel;
|
|
165
165
|
const config = { ...DEFAULT_ANT_CONFIGS[caste], model: casteModel };
|
|
@@ -168,7 +168,19 @@ async function runAntWave(opts: WaveOptions): Promise<"ok"> {
|
|
|
168
168
|
let consecutiveRateLimits = 0; // 连续限流计数
|
|
169
169
|
const retriedTasks = new Set<string>(); // 防止重复重试
|
|
170
170
|
|
|
171
|
-
const runOne = async (): Promise<"done" | "empty" | "rate_limited"> => {
|
|
171
|
+
const runOne = async (): Promise<"done" | "empty" | "rate_limited" | "budget"> => {
|
|
172
|
+
// Budget 刹车:剩余预算不够一只蚂蚁的预估成本就不出发
|
|
173
|
+
const state = nest.getState();
|
|
174
|
+
if (state.maxCost != null && caste !== "drone") {
|
|
175
|
+
const spent = state.ants.reduce((s, a) => s + a.usage.cost, 0);
|
|
176
|
+
const remaining = state.maxCost - spent;
|
|
177
|
+
const doneAnts = state.ants.filter(a => a.status === "done" && a.usage.cost > 0);
|
|
178
|
+
const avgCost = doneAnts.length > 0
|
|
179
|
+
? doneAnts.reduce((s, a) => s + a.usage.cost, 0) / doneAnts.length
|
|
180
|
+
: 0.05;
|
|
181
|
+
if (remaining < avgCost * 1.5) return "budget";
|
|
182
|
+
}
|
|
183
|
+
|
|
172
184
|
const task = nest.nextPendingTask(caste);
|
|
173
185
|
if (!task) return "empty";
|
|
174
186
|
if (!nest.claimTask(task.id, "queen")) return "empty";
|
|
@@ -280,12 +292,16 @@ async function runAntWave(opts: WaveOptions): Promise<"ok"> {
|
|
|
280
292
|
}
|
|
281
293
|
|
|
282
294
|
const batch = Math.min(slotsAvailable, pending.length);
|
|
283
|
-
const promises: Promise<"done" | "empty" | "rate_limited">[] = [];
|
|
295
|
+
const promises: Promise<"done" | "empty" | "rate_limited" | "budget">[] = [];
|
|
284
296
|
for (let i = 0; i < batch; i++) {
|
|
285
297
|
promises.push(runOne());
|
|
286
298
|
}
|
|
287
299
|
const results = await Promise.all(promises);
|
|
288
300
|
|
|
301
|
+
if (results.includes("budget")) {
|
|
302
|
+
return "budget";
|
|
303
|
+
}
|
|
304
|
+
|
|
289
305
|
// 429 处理:降低并发 + 渐进退避(2s → 5s → 10s,上限 10s)
|
|
290
306
|
if (results.includes("rate_limited")) {
|
|
291
307
|
consecutiveRateLimits++;
|
|
@@ -431,9 +447,8 @@ export async function runColony(opts: QueenOptions): Promise<ColonyState> {
|
|
|
431
447
|
emitSignal("working", `${workerTasks.length} tasks to do`);
|
|
432
448
|
await runAntWave({ ...waveBase, caste: "worker" });
|
|
433
449
|
|
|
434
|
-
//
|
|
435
|
-
|
|
436
|
-
while (rounds < 3) {
|
|
450
|
+
// 处理工蚁产生的子任务(budget 驱动,无硬限制)
|
|
451
|
+
while (true) {
|
|
437
452
|
// 先跑 drone 子任务
|
|
438
453
|
const pendingDrones = nest.getAllTasks().filter(t => t.caste === "drone" && t.status === "pending");
|
|
439
454
|
if (pendingDrones.length > 0) await runAntWave({ ...waveBase, caste: "drone" });
|
|
@@ -442,9 +457,15 @@ export async function runColony(opts: QueenOptions): Promise<ColonyState> {
|
|
|
442
457
|
t.caste === "worker" && (t.status === "pending" || t.status === "blocked")
|
|
443
458
|
);
|
|
444
459
|
if (remaining.length === 0) break;
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
460
|
+
callbacks.onPhase?.("working", `${remaining.length} sub-tasks from workers...`);
|
|
461
|
+
const result = await runAntWave({ ...waveBase, caste: "worker" });
|
|
462
|
+
if (result === "budget") {
|
|
463
|
+
nest.updateState({ status: "budget_exceeded", finishedAt: Date.now() });
|
|
464
|
+
emitSignal("budget_exceeded", "Budget exhausted");
|
|
465
|
+
const budgetState = nest.getState();
|
|
466
|
+
callbacks.onComplete?.(budgetState);
|
|
467
|
+
return budgetState;
|
|
468
|
+
}
|
|
448
469
|
}
|
|
449
470
|
|
|
450
471
|
// ═══ Auto-check: run tsc before soldier review ═══
|