oh-pi 0.1.51 → 0.1.52
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 +1 -1
- package/pi-package/agents/colony-operator.md +1 -1
- package/pi-package/extensions/ant-colony/README.md +5 -6
- package/pi-package/extensions/ant-colony/index.ts +71 -14
- package/pi-package/extensions/ant-colony/queen.ts +3 -0
- package/pi-package/skills/ant-colony/SKILL.md +0 -59
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@ You command an autonomous ant colony. Complex tasks are delegated to the swarm,
|
|
|
16
16
|
|
|
17
17
|
## Workflow
|
|
18
18
|
1. Assess task scope
|
|
19
|
-
2. If colony-worthy → use
|
|
19
|
+
2. If colony-worthy → use `ant_colony` tool with clear goal
|
|
20
20
|
3. If simple → do it directly
|
|
21
21
|
4. Review colony output, fix gaps manually if needed
|
|
22
22
|
|
|
@@ -36,16 +36,15 @@
|
|
|
36
36
|
|
|
37
37
|
## 使用方式
|
|
38
38
|
|
|
39
|
-
###
|
|
39
|
+
### 使用方式
|
|
40
40
|
|
|
41
|
-
LLM
|
|
41
|
+
LLM 在判断任务复杂度足够时会自动调用 `ant_colony` tool,无需手动触发。
|
|
42
42
|
|
|
43
43
|
### 命令
|
|
44
44
|
|
|
45
45
|
```
|
|
46
|
-
/colony
|
|
47
|
-
|
|
48
|
-
Ctrl+Alt+A 快捷启动
|
|
46
|
+
/colony-stop 中止运行中的蚁群
|
|
47
|
+
Ctrl+Shift+A 展开蚁群详情面板
|
|
49
48
|
```
|
|
50
49
|
|
|
51
50
|
### 示例
|
|
@@ -114,4 +113,4 @@ npx oh-pi # 选择 Full Power 预设
|
|
|
114
113
|
| `concurrency.ts` | 115 | 自适应并发:系统采样,探索/稳态双阶段调节 |
|
|
115
114
|
| `spawner.ts` | 316 | 蚂蚁孵化:进程管理,prompt 构建,输出解析 |
|
|
116
115
|
| `queen.ts` | 331 | 女王调度:生命周期,任务波次,多轮迭代 |
|
|
117
|
-
| `index.ts` | 324 | 扩展入口:tool/
|
|
116
|
+
| `index.ts` | 324 | 扩展入口:tool/shortcut 注册,TUI 渲染 |
|
|
@@ -467,37 +467,94 @@ export default function antColonyExtension(pi: ExtensionAPI) {
|
|
|
467
467
|
},
|
|
468
468
|
});
|
|
469
469
|
|
|
470
|
-
// ═══
|
|
471
|
-
pi.
|
|
472
|
-
|
|
470
|
+
// ═══ Tool: ant_colony ═══
|
|
471
|
+
pi.registerTool({
|
|
472
|
+
name: "ant_colony",
|
|
473
|
+
label: "Ant Colony",
|
|
474
|
+
description: [
|
|
475
|
+
"Launch an autonomous ant colony in the BACKGROUND to accomplish a complex goal.",
|
|
476
|
+
"The colony runs asynchronously — you can continue chatting while it works.",
|
|
477
|
+
"Results are automatically injected when the colony finishes.",
|
|
478
|
+
"Scouts explore the codebase, workers execute tasks in parallel, soldiers review quality.",
|
|
479
|
+
"Use for multi-file changes, large refactors, or complex features.",
|
|
480
|
+
].join(" "),
|
|
473
481
|
parameters: Type.Object({
|
|
474
482
|
goal: Type.String({ description: "What the colony should accomplish" }),
|
|
483
|
+
maxAnts: Type.Optional(Type.Number({ description: "Max concurrent ants (default: auto-adapt)", minimum: 1, maximum: 8 })),
|
|
484
|
+
maxCost: Type.Optional(Type.Number({ description: "Max cost budget in USD (default: unlimited)", minimum: 0.01 })),
|
|
485
|
+
scoutModel: Type.Optional(Type.String({ description: "Model for scout ants (default: current session model)" })),
|
|
486
|
+
workerModel: Type.Optional(Type.String({ description: "Model for worker ants (default: current session model)" })),
|
|
487
|
+
soldierModel: Type.Optional(Type.String({ description: "Model for soldier ants (default: current session model)" })),
|
|
475
488
|
}),
|
|
476
|
-
|
|
489
|
+
|
|
490
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
491
|
+
if (activeColony) {
|
|
492
|
+
return {
|
|
493
|
+
content: [{ type: "text", text: "A colony is already running in the background. Use /colony-stop to cancel it first." }],
|
|
494
|
+
isError: true,
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
|
|
477
498
|
const currentModel = ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : null;
|
|
478
499
|
if (!currentModel) {
|
|
479
|
-
|
|
480
|
-
|
|
500
|
+
return {
|
|
501
|
+
content: [{ type: "text", text: "Colony failed: no model available in current session" }],
|
|
502
|
+
isError: true,
|
|
503
|
+
};
|
|
481
504
|
}
|
|
482
505
|
|
|
506
|
+
const modelOverrides: Record<string, string> = {};
|
|
507
|
+
if (params.scoutModel) modelOverrides.scout = params.scoutModel;
|
|
508
|
+
if (params.workerModel) modelOverrides.worker = params.workerModel;
|
|
509
|
+
if (params.soldierModel) modelOverrides.soldier = params.soldierModel;
|
|
510
|
+
|
|
483
511
|
const colonyParams = {
|
|
484
|
-
goal:
|
|
512
|
+
goal: params.goal,
|
|
513
|
+
maxAnts: params.maxAnts,
|
|
514
|
+
maxCost: params.maxCost,
|
|
485
515
|
currentModel,
|
|
486
|
-
modelOverrides
|
|
516
|
+
modelOverrides,
|
|
487
517
|
cwd: ctx.cwd,
|
|
488
518
|
modelRegistry: ctx.modelRegistry ?? undefined,
|
|
489
519
|
};
|
|
490
520
|
|
|
521
|
+
// 非交互模式(print mode):同步等待蚁群完成
|
|
491
522
|
if (!ctx.hasUI) {
|
|
492
|
-
|
|
493
|
-
if (result.isError) {
|
|
494
|
-
ctx.ui.notify("Colony failed", "error");
|
|
495
|
-
}
|
|
496
|
-
return;
|
|
523
|
+
return await runSyncColony(colonyParams, _signal);
|
|
497
524
|
}
|
|
498
525
|
|
|
526
|
+
// 交互模式:后台运行
|
|
499
527
|
launchBackgroundColony(colonyParams);
|
|
500
|
-
|
|
528
|
+
|
|
529
|
+
return {
|
|
530
|
+
content: [{ type: "text", text: `[COLONY_SIGNAL:LAUNCHED]\n🐜 Colony launched in background.\nGoal: ${params.goal}\n\nThe colony is now running autonomously. Results will be injected when it finishes.` }],
|
|
531
|
+
};
|
|
532
|
+
},
|
|
533
|
+
|
|
534
|
+
renderCall(args, theme) {
|
|
535
|
+
const goal = args.goal?.length > 70 ? args.goal.slice(0, 67) + "..." : args.goal;
|
|
536
|
+
let text = theme.fg("toolTitle", theme.bold("🐜 ant_colony"));
|
|
537
|
+
if (args.maxAnts) text += theme.fg("muted", ` ×${args.maxAnts}`);
|
|
538
|
+
if (args.maxCost) text += theme.fg("warning", ` $${args.maxCost}`);
|
|
539
|
+
text += "\n" + theme.fg("dim", ` ${goal || "..."}`);
|
|
540
|
+
return new Text(text, 0, 0);
|
|
541
|
+
},
|
|
542
|
+
|
|
543
|
+
renderResult(result, { expanded }, theme) {
|
|
544
|
+
const text = result.content?.find((c: any) => c.type === "text")?.text || "";
|
|
545
|
+
if (result.isError) {
|
|
546
|
+
return new Text(theme.fg("error", text), 0, 0);
|
|
547
|
+
}
|
|
548
|
+
const container = new Container();
|
|
549
|
+
container.addChild(new Text(
|
|
550
|
+
theme.fg("success", "✓ ") + theme.fg("toolTitle", theme.bold("Colony launched in background")),
|
|
551
|
+
0, 0,
|
|
552
|
+
));
|
|
553
|
+
if (activeColony) {
|
|
554
|
+
container.addChild(new Text(theme.fg("dim", ` Goal: ${activeColony.goal.slice(0, 70)}`), 0, 0));
|
|
555
|
+
container.addChild(new Text(theme.fg("muted", ` Ctrl+Shift+A for details │ /colony-stop to cancel`), 0, 0));
|
|
556
|
+
}
|
|
557
|
+
return container;
|
|
501
558
|
},
|
|
502
559
|
});
|
|
503
560
|
|
|
@@ -290,6 +290,9 @@ async function runAntWave(opts: WaveOptions): Promise<"ok"> {
|
|
|
290
290
|
* 蚁后主循环
|
|
291
291
|
*/
|
|
292
292
|
export async function runColony(opts: QueenOptions): Promise<ColonyState> {
|
|
293
|
+
if (!opts.goal || !opts.goal.trim()) {
|
|
294
|
+
throw new Error("Colony goal is empty or undefined. Please provide a clear goal.");
|
|
295
|
+
}
|
|
293
296
|
const colonyId = makeColonyId();
|
|
294
297
|
const nest = new Nest(opts.cwd, colonyId);
|
|
295
298
|
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: ant-colony
|
|
3
|
-
description: Ant colony multi-agent orchestration. Use when user needs parallel multi-file changes, large refactors, or complex features. Provides colony management commands and strategies.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Ant Colony Skill
|
|
7
|
-
|
|
8
|
-
## When to Use
|
|
9
|
-
- Multi-file changes (≥3 files)
|
|
10
|
-
- Parallel workstreams
|
|
11
|
-
- Large refactors, migrations
|
|
12
|
-
- User says: colony, swarm, parallel, multi-agent
|
|
13
|
-
|
|
14
|
-
## Quick Start
|
|
15
|
-
```
|
|
16
|
-
/colony <goal>
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Colony Lifecycle
|
|
20
|
-
1. **Scout** — Explore codebase, identify targets, produce task pool
|
|
21
|
-
2. **Work** — Workers execute in parallel, adaptive concurrency
|
|
22
|
-
3. **Review** — Soldiers audit changes, request fixes if needed
|
|
23
|
-
4. **Fix** — Workers address review findings
|
|
24
|
-
5. **Done** — Summary report
|
|
25
|
-
|
|
26
|
-
## Strategies
|
|
27
|
-
|
|
28
|
-
### File-Scoped Decomposition (default)
|
|
29
|
-
Each worker owns distinct files. Zero conflict.
|
|
30
|
-
```
|
|
31
|
-
Worker A: [src/auth.ts, src/auth.test.ts]
|
|
32
|
-
Worker B: [src/api.ts, src/api.test.ts]
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Module-Scoped
|
|
36
|
-
Each worker owns a module directory.
|
|
37
|
-
```
|
|
38
|
-
Worker A: src/components/
|
|
39
|
-
Worker B: src/api/
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Pipeline
|
|
43
|
-
Sequential handoff when dependencies exist.
|
|
44
|
-
```
|
|
45
|
-
Scout → Worker(schema) → Worker(api) → Worker(ui) → Soldier
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Tuning
|
|
49
|
-
- `maxAnts`: Cap concurrent ants (default: auto-adapt to CPU)
|
|
50
|
-
- Colony auto-reduces concurrency on 429 rate limits
|
|
51
|
-
- Blocked tasks auto-resume when file locks release
|
|
52
|
-
|
|
53
|
-
## Extending Castes
|
|
54
|
-
Add custom ant types by editing `ant-colony/types.ts`:
|
|
55
|
-
```typescript
|
|
56
|
-
// In DEFAULT_ANT_CONFIGS, add:
|
|
57
|
-
mycaste: { caste: "mycaste", model: "...", tools: [...], maxTurns: 10 }
|
|
58
|
-
```
|
|
59
|
-
Then add matching prompt in `spawner.ts` CASTE_PROMPTS.
|