oh-pi 0.1.21 → 0.1.23
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/README.fr.md +196 -0
- package/README.md +3 -1
- package/README.zh.md +196 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/pi-package/extensions/ant-colony/index.ts +15 -2
- package/pi-package/extensions/ant-colony/queen.ts +40 -8
- package/pi-package/extensions/ant-colony/types.ts +6 -1
- package/pi-package/extensions/custom-footer.ts +4 -2
package/README.fr.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="./logo.svg" width="180" alt="oh-pi logo"/>
|
|
4
|
+
|
|
5
|
+
# 🐜 oh-pi
|
|
6
|
+
|
|
7
|
+
**Une seule commande pour booster [pi-coding-agent](https://github.com/badlogic/pi-mono).**
|
|
8
|
+
|
|
9
|
+
Comme oh-my-zsh pour pi — mais avec une colonie de fourmis autonome.
|
|
10
|
+
|
|
11
|
+
[](https://www.npmjs.com/package/oh-pi)
|
|
12
|
+
[](./LICENSE)
|
|
13
|
+
[](https://nodejs.org)
|
|
14
|
+
|
|
15
|
+
[English](./README.md) | [中文](./README.zh.md) | [Français](./README.fr.md)
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx oh-pi
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Pourquoi
|
|
26
|
+
|
|
27
|
+
pi-coding-agent est puissant dès l'installation. Mais configurer manuellement les fournisseurs, thèmes, extensions, compétences et modèles de prompts est fastidieux. oh-pi vous offre une TUI moderne qui fait tout en moins d'une minute — et intègre un **essaim de fourmis** qui transforme pi en système multi-agents.
|
|
28
|
+
|
|
29
|
+
## Démarrage rapide
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npx oh-pi # tout configurer
|
|
33
|
+
pi # commencer à coder
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
C'est tout. oh-pi détecte votre environnement, vous guide dans la configuration et génère `~/.pi/agent/` pour vous.
|
|
37
|
+
|
|
38
|
+
Vous avez déjà une config ? oh-pi la détecte et propose une **sauvegarde avant écrasement**.
|
|
39
|
+
|
|
40
|
+
## Ce que vous obtenez
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
~/.pi/agent/
|
|
44
|
+
├── auth.json Clés API (permissions 0600)
|
|
45
|
+
├── settings.json Modèle, thème, niveau de réflexion
|
|
46
|
+
├── keybindings.json Raccourcis Vim/Emacs (optionnel)
|
|
47
|
+
├── AGENTS.md Directives IA par rôle
|
|
48
|
+
├── extensions/ 4 extensions
|
|
49
|
+
│ ├── safe-guard Confirmation des commandes dangereuses + protection des chemins
|
|
50
|
+
│ ├── git-guard Checkpoints auto stash + alerte dépôt modifié
|
|
51
|
+
│ ├── auto-session Nommage de session depuis le premier message
|
|
52
|
+
│ └── ant-colony/ 🐜 Essaim multi-agents autonome
|
|
53
|
+
├── prompts/ 10 modèles (/review /fix /commit /test ...)
|
|
54
|
+
├── skills/ 4 compétences (debug, git, setup, colony)
|
|
55
|
+
└── themes/ 6 thèmes personnalisés
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Modes de configuration
|
|
59
|
+
|
|
60
|
+
| Mode | Étapes | Pour |
|
|
61
|
+
|------|--------|------|
|
|
62
|
+
| 🚀 **Rapide** | 3 | Choisir fournisseur → entrer la clé → terminé |
|
|
63
|
+
| 📦 **Préréglage** | 2 | Choisir un profil de rôle → entrer la clé |
|
|
64
|
+
| 🎛️ **Personnalisé** | 6 | Tout choisir soi-même |
|
|
65
|
+
|
|
66
|
+
### Préréglages
|
|
67
|
+
|
|
68
|
+
| | Thème | Réflexion | Inclut |
|
|
69
|
+
|---|-------|-----------|--------|
|
|
70
|
+
| 🟢 Débutant | oh-pi Dark | moyen | Sécurité + bases git |
|
|
71
|
+
| 🔵 Développeur Pro | Catppuccin | élevé | Chaîne d'outils complète |
|
|
72
|
+
| 🟣 Chercheur en sécurité | Cyberpunk | élevé | Audit + pentesting |
|
|
73
|
+
| 🟠 Data & IA | Tokyo Night | moyen | MLOps + pipelines |
|
|
74
|
+
| 🔴 Minimal | Default | désactivé | Noyau uniquement |
|
|
75
|
+
| ⚫ Pleine puissance | oh-pi Dark | élevé | Tout + colonie de fourmis |
|
|
76
|
+
|
|
77
|
+
### Fournisseurs
|
|
78
|
+
|
|
79
|
+
Anthropic · OpenAI · Google Gemini · Groq · OpenRouter · xAI · Mistral · [FOXNIO](https://www.foxnio.com) (fournisseur Claude d'intérêt public recommandé)
|
|
80
|
+
|
|
81
|
+
Détection automatique des clés API depuis les variables d'environnement.
|
|
82
|
+
|
|
83
|
+
## 🐜 Colonie de fourmis
|
|
84
|
+
|
|
85
|
+
La fonctionnalité phare. Un essaim multi-agents inspiré de l'écologie réelle des fourmis.
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
Vous : "Refactorer l'auth des sessions vers JWT"
|
|
89
|
+
|
|
90
|
+
oh-pi :
|
|
91
|
+
🔍 Fourmis éclaireuses explorent le code (haiku — rapide, économique)
|
|
92
|
+
📋 Pool de tâches généré à partir des découvertes
|
|
93
|
+
⚒️ Fourmis ouvrières exécutent en parallèle (sonnet — capable)
|
|
94
|
+
🛡️ Fourmis soldats révisent tous les changements (sonnet — minutieux)
|
|
95
|
+
✅ Terminé — rapport de synthèse avec métriques
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Pourquoi des fourmis ?
|
|
99
|
+
|
|
100
|
+
Les vraies colonies de fourmis résolvent des problèmes complexes sans contrôle central. Chaque fourmi suit des règles simples, communique par **pistes de phéromones**, et la colonie s'auto-organise. oh-pi reproduit directement ce modèle :
|
|
101
|
+
|
|
102
|
+
| Vraies fourmis | oh-pi |
|
|
103
|
+
|----------------|-------|
|
|
104
|
+
| L'éclaireuse trouve la nourriture | L'éclaireuse scanne le code, identifie les cibles |
|
|
105
|
+
| Piste de phéromones | `.ant-colony/pheromone.jsonl` — découvertes partagées |
|
|
106
|
+
| L'ouvrière transporte la nourriture | L'ouvrière exécute la tâche sur les fichiers assignés |
|
|
107
|
+
| Le soldat garde le nid | Le soldat révise les changements, demande des corrections |
|
|
108
|
+
| Plus de nourriture → plus de fourmis | Plus de tâches → concurrence plus élevée (auto-adaptée) |
|
|
109
|
+
| Les phéromones s'évaporent | Demi-vie de 10 min — les infos obsolètes s'estompent |
|
|
110
|
+
|
|
111
|
+
### Déclenchement automatique
|
|
112
|
+
|
|
113
|
+
Le LLM décide quand déployer la colonie. Vous n'avez pas à y penser :
|
|
114
|
+
|
|
115
|
+
- **≥3 fichiers** à modifier → colonie
|
|
116
|
+
- **Flux de travail parallèles** possibles → colonie
|
|
117
|
+
- **Un seul fichier** à modifier → exécution directe (pas de surcharge colonie)
|
|
118
|
+
|
|
119
|
+
Ou déclencher manuellement :
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
/colony migrer tout le projet de CJS vers ESM
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Concurrence adaptative
|
|
126
|
+
|
|
127
|
+
La colonie trouve automatiquement le parallélisme optimal pour votre machine :
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
Démarrage à froid → 1-2 fourmis (conservateur)
|
|
131
|
+
Exploration → +1 par vague, surveillance du débit
|
|
132
|
+
Débit en baisse → verrouiller l'optimal, stabiliser
|
|
133
|
+
CPU > 85% → réduire immédiatement
|
|
134
|
+
429 rate limit → diviser la concurrence par 2 + backoff exponentiel (15s→30s→60s)
|
|
135
|
+
Tâches terminées → réduire au minimum
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Sécurité des fichiers
|
|
139
|
+
|
|
140
|
+
Une fourmi par fichier. Toujours. Les tâches en conflit sont automatiquement bloquées et reprennent à la libération des verrous.
|
|
141
|
+
|
|
142
|
+
## Thèmes
|
|
143
|
+
|
|
144
|
+
| | |
|
|
145
|
+
|---|---|
|
|
146
|
+
| 🌙 **oh-pi Dark** | Cyan + violet, contraste élevé |
|
|
147
|
+
| 🌙 **Cyberpunk** | Magenta néon + cyan électrique |
|
|
148
|
+
| 🌙 **Nord** | Palette bleu arctique |
|
|
149
|
+
| 🌙 **Catppuccin Mocha** | Pastel sur fond sombre |
|
|
150
|
+
| 🌙 **Tokyo Night** | Crépuscule bleu + violet |
|
|
151
|
+
| 🌙 **Gruvbox Dark** | Tons rétro chaleureux |
|
|
152
|
+
|
|
153
|
+
## Modèles de prompts
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
/review Revue de code : bugs, sécurité, performance
|
|
157
|
+
/fix Corriger les erreurs avec un minimum de changements
|
|
158
|
+
/explain Expliquer le code, du simple au détaillé
|
|
159
|
+
/refactor Refactorer en préservant le comportement
|
|
160
|
+
/test Générer des tests
|
|
161
|
+
/commit Message Conventional Commit
|
|
162
|
+
/pr Description de Pull Request
|
|
163
|
+
/security Audit de sécurité OWASP
|
|
164
|
+
/optimize Optimisation des performances
|
|
165
|
+
/document Générer la documentation
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Modèles AGENTS.md
|
|
169
|
+
|
|
170
|
+
| Modèle | Focus |
|
|
171
|
+
|--------|-------|
|
|
172
|
+
| Développeur généraliste | Directives de codage universelles |
|
|
173
|
+
| Développeur Full-Stack | Frontend + backend + BDD |
|
|
174
|
+
| Chercheur en sécurité | Pentesting & audit |
|
|
175
|
+
| Ingénieur Data & IA | MLOps & pipelines |
|
|
176
|
+
| 🐜 Opérateur de colonie | Orchestration multi-agents |
|
|
177
|
+
|
|
178
|
+
## Aussi un package Pi
|
|
179
|
+
|
|
180
|
+
Passez le configurateur, installez directement les ressources :
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
pi install npm:oh-pi
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Ajoute tous les thèmes, prompts, compétences et extensions à votre configuration pi existante.
|
|
187
|
+
|
|
188
|
+
## Prérequis
|
|
189
|
+
|
|
190
|
+
- Node.js ≥ 20
|
|
191
|
+
- Au moins une clé API LLM
|
|
192
|
+
- pi-coding-agent (installé automatiquement si absent)
|
|
193
|
+
|
|
194
|
+
## Licence
|
|
195
|
+
|
|
196
|
+
MIT
|
package/README.md
CHANGED
|
@@ -12,6 +12,8 @@ Like oh-my-zsh for pi — but with an autonomous ant colony.
|
|
|
12
12
|
[](./LICENSE)
|
|
13
13
|
[](https://nodejs.org)
|
|
14
14
|
|
|
15
|
+
[English](./README.md) | [中文](./README.zh.md) | [Français](./README.fr.md)
|
|
16
|
+
|
|
15
17
|
```bash
|
|
16
18
|
npx oh-pi
|
|
17
19
|
```
|
|
@@ -74,7 +76,7 @@ Already have a config? oh-pi detects it and offers **backup before overwriting**
|
|
|
74
76
|
|
|
75
77
|
### Providers
|
|
76
78
|
|
|
77
|
-
Anthropic · OpenAI · Google Gemini · Groq · OpenRouter · xAI · Mistral
|
|
79
|
+
Anthropic · OpenAI · Google Gemini · Groq · OpenRouter · xAI · Mistral · [FOXNIO](https://www.foxnio.com) (recommended public-benefit Claude provider)
|
|
78
80
|
|
|
79
81
|
Auto-detects API keys from environment variables.
|
|
80
82
|
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="./logo.svg" width="180" alt="oh-pi logo"/>
|
|
4
|
+
|
|
5
|
+
# 🐜 oh-pi
|
|
6
|
+
|
|
7
|
+
**一条命令,增强 [pi-coding-agent](https://github.com/badlogic/pi-mono)。**
|
|
8
|
+
|
|
9
|
+
就像 oh-my-zsh 之于 pi —— 但带有自主蚁群系统。
|
|
10
|
+
|
|
11
|
+
[](https://www.npmjs.com/package/oh-pi)
|
|
12
|
+
[](./LICENSE)
|
|
13
|
+
[](https://nodejs.org)
|
|
14
|
+
|
|
15
|
+
[English](./README.md) | [中文](./README.zh.md) | [Français](./README.fr.md)
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx oh-pi
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 为什么选择 oh-pi
|
|
26
|
+
|
|
27
|
+
pi-coding-agent 开箱即用已经很强大,但手动配置供应商、主题、扩展、技能和提示词模板非常繁琐。oh-pi 提供现代化 TUI,一分钟内搞定一切 —— 还附带**蚁群集群**,将 pi 变成多智能体系统。
|
|
28
|
+
|
|
29
|
+
## 快速开始
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npx oh-pi # 配置一切
|
|
33
|
+
pi # 开始编码
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
就这么简单。oh-pi 检测你的环境,引导你完成设置,并为你生成 `~/.pi/agent/` 配置。
|
|
37
|
+
|
|
38
|
+
已有配置?oh-pi 会检测到并提供**覆盖前备份**。
|
|
39
|
+
|
|
40
|
+
## 你将获得
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
~/.pi/agent/
|
|
44
|
+
├── auth.json API 密钥(0600 权限)
|
|
45
|
+
├── settings.json 模型、主题、思考级别
|
|
46
|
+
├── keybindings.json Vim/Emacs 快捷键(可选)
|
|
47
|
+
├── AGENTS.md 角色专属 AI 指南
|
|
48
|
+
├── extensions/ 4 个扩展
|
|
49
|
+
│ ├── safe-guard 危险命令确认 + 路径保护
|
|
50
|
+
│ ├── git-guard 自动 stash 检查点 + 脏仓库警告
|
|
51
|
+
│ ├── auto-session 根据首条消息自动命名会话
|
|
52
|
+
│ └── ant-colony/ 🐜 自主多智能体蚁群
|
|
53
|
+
├── prompts/ 10 个模板(/review /fix /commit /test ...)
|
|
54
|
+
├── skills/ 4 个技能(debug、git、setup、colony)
|
|
55
|
+
└── themes/ 6 个自定义主题
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## 设置模式
|
|
59
|
+
|
|
60
|
+
| 模式 | 步骤 | 适用场景 |
|
|
61
|
+
|------|------|----------|
|
|
62
|
+
| 🚀 **快速** | 3 | 选供应商 → 输入密钥 → 完成 |
|
|
63
|
+
| 📦 **预设** | 2 | 选择角色配置 → 输入密钥 |
|
|
64
|
+
| 🎛️ **自定义** | 6 | 自己选择所有选项 |
|
|
65
|
+
|
|
66
|
+
### 预设方案
|
|
67
|
+
|
|
68
|
+
| | 主题 | 思考级别 | 包含 |
|
|
69
|
+
|---|------|----------|------|
|
|
70
|
+
| 🟢 入门 | oh-pi Dark | 中等 | 安全 + git 基础 |
|
|
71
|
+
| 🔵 专业开发者 | Catppuccin | 高 | 完整工具链 |
|
|
72
|
+
| 🟣 安全研究员 | Cyberpunk | 高 | 审计 + 渗透测试 |
|
|
73
|
+
| 🟠 数据 & AI | Tokyo Night | 中等 | MLOps + 流水线 |
|
|
74
|
+
| 🔴 极简 | Default | 关闭 | 仅核心功能 |
|
|
75
|
+
| ⚫ 全功率 | oh-pi Dark | 高 | 所有功能 + 蚁群 |
|
|
76
|
+
|
|
77
|
+
### 供应商
|
|
78
|
+
|
|
79
|
+
Anthropic · OpenAI · Google Gemini · Groq · OpenRouter · xAI · Mistral · [FOXNIO](https://www.foxnio.com)(推荐公益 Claude 供应商)
|
|
80
|
+
|
|
81
|
+
自动从环境变量检测 API 密钥。
|
|
82
|
+
|
|
83
|
+
## 🐜 蚁群系统
|
|
84
|
+
|
|
85
|
+
核心特性。模拟真实蚂蚁生态的多智能体集群。
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
你:"把认证从 session 重构为 JWT"
|
|
89
|
+
|
|
90
|
+
oh-pi:
|
|
91
|
+
🔍 侦察蚁探索代码库(haiku — 快速、低成本)
|
|
92
|
+
📋 根据发现生成任务池
|
|
93
|
+
⚒️ 工蚁并行执行任务(sonnet — 能力强)
|
|
94
|
+
🛡️ 兵蚁审查所有变更(sonnet — 细致)
|
|
95
|
+
✅ 完成 — 汇总报告及指标
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 为什么是蚂蚁?
|
|
99
|
+
|
|
100
|
+
真实蚁群无需中央控制即可解决复杂问题。每只蚂蚁遵循简单规则,通过**信息素轨迹**通信,蚁群自组织运作。oh-pi 直接映射了这一模型:
|
|
101
|
+
|
|
102
|
+
| 真实蚂蚁 | oh-pi |
|
|
103
|
+
|----------|-------|
|
|
104
|
+
| 侦察蚁发现食物 | 侦察蚁扫描代码库,识别目标 |
|
|
105
|
+
| 信息素轨迹 | `.ant-colony/pheromone.jsonl` — 共享发现 |
|
|
106
|
+
| 工蚁搬运食物 | 工蚁在分配的文件上执行任务 |
|
|
107
|
+
| 兵蚁守卫巢穴 | 兵蚁审查变更,请求修复 |
|
|
108
|
+
| 食物越多 → 蚂蚁越多 | 任务越多 → 并发越高(自动适配) |
|
|
109
|
+
| 信息素蒸发 | 10 分钟半衰期 — 过时信息自动淡化 |
|
|
110
|
+
|
|
111
|
+
### 自动触发
|
|
112
|
+
|
|
113
|
+
LLM 自行决定何时部署蚁群,你无需操心:
|
|
114
|
+
|
|
115
|
+
- **≥3 个文件**需要修改 → 蚁群
|
|
116
|
+
- 可**并行工作流** → 蚁群
|
|
117
|
+
- **单文件**修改 → 直接执行(无蚁群开销)
|
|
118
|
+
|
|
119
|
+
或手动触发:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
/colony 将整个项目从 CJS 迁移到 ESM
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 自适应并发
|
|
126
|
+
|
|
127
|
+
蚁群自动为你的机器找到最优并行度:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
冷启动 → 1-2 只蚂蚁(保守)
|
|
131
|
+
探索阶段 → 每波 +1,监控吞吐量
|
|
132
|
+
吞吐量下降 → 锁定最优值,稳定运行
|
|
133
|
+
CPU > 85% → 立即减少
|
|
134
|
+
429 限流 → 并发减半 + 指数退避(15s→30s→60s)
|
|
135
|
+
任务完成 → 缩减至最小值
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 文件安全
|
|
139
|
+
|
|
140
|
+
一个文件一只蚂蚁,始终如此。冲突任务自动阻塞,锁释放后恢复执行。
|
|
141
|
+
|
|
142
|
+
## 主题
|
|
143
|
+
|
|
144
|
+
| | |
|
|
145
|
+
|---|---|
|
|
146
|
+
| 🌙 **oh-pi Dark** | 青色 + 紫色,高对比度 |
|
|
147
|
+
| 🌙 **Cyberpunk** | 霓虹洋红 + 电光青 |
|
|
148
|
+
| 🌙 **Nord** | 北极蓝色调 |
|
|
149
|
+
| 🌙 **Catppuccin Mocha** | 暗底柔和色 |
|
|
150
|
+
| 🌙 **Tokyo Night** | 蓝紫暮光 |
|
|
151
|
+
| 🌙 **Gruvbox Dark** | 暖色复古风 |
|
|
152
|
+
|
|
153
|
+
## 提示词模板
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
/review 代码审查:bug、安全、性能
|
|
157
|
+
/fix 最小改动修复错误
|
|
158
|
+
/explain 代码解释,由浅入深
|
|
159
|
+
/refactor 保持行为的重构
|
|
160
|
+
/test 生成测试
|
|
161
|
+
/commit Conventional Commit 提交信息
|
|
162
|
+
/pr Pull Request 描述
|
|
163
|
+
/security OWASP 安全审计
|
|
164
|
+
/optimize 性能优化
|
|
165
|
+
/document 生成文档
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## AGENTS.md 模板
|
|
169
|
+
|
|
170
|
+
| 模板 | 侧重 |
|
|
171
|
+
|------|------|
|
|
172
|
+
| 通用开发者 | 通用编码指南 |
|
|
173
|
+
| 全栈开发者 | 前端 + 后端 + 数据库 |
|
|
174
|
+
| 安全研究员 | 渗透测试 & 审计 |
|
|
175
|
+
| 数据 & AI 工程师 | MLOps & 流水线 |
|
|
176
|
+
| 🐜 蚁群操作员 | 多智能体编排 |
|
|
177
|
+
|
|
178
|
+
## 也是 Pi 包
|
|
179
|
+
|
|
180
|
+
跳过配置器,直接安装资源:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
pi install npm:oh-pi
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
将所有主题、提示词、技能和扩展添加到你现有的 pi 配置中。
|
|
187
|
+
|
|
188
|
+
## 环境要求
|
|
189
|
+
|
|
190
|
+
- Node.js ≥ 20
|
|
191
|
+
- 至少一个 LLM API 密钥
|
|
192
|
+
- pi-coding-agent(缺失时自动安装)
|
|
193
|
+
|
|
194
|
+
## 许可证
|
|
195
|
+
|
|
196
|
+
MIT
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -37,7 +37,7 @@ function formatTokens(n: number): string {
|
|
|
37
37
|
function statusIcon(status: string): string {
|
|
38
38
|
const icons: Record<string, string> = {
|
|
39
39
|
scouting: "🔍", working: "⚒️", reviewing: "🛡️",
|
|
40
|
-
done: "✅", failed: "❌",
|
|
40
|
+
done: "✅", failed: "❌", budget_exceeded: "💰",
|
|
41
41
|
};
|
|
42
42
|
return icons[status] || "🐜";
|
|
43
43
|
}
|
|
@@ -79,11 +79,20 @@ For simple single-file tasks, work directly without the colony.`,
|
|
|
79
79
|
parameters: Type.Object({
|
|
80
80
|
goal: Type.String({ description: "What the colony should accomplish" }),
|
|
81
81
|
maxAnts: Type.Optional(Type.Number({ description: "Max concurrent ants (default: auto-adapt)", minimum: 1, maximum: 8 })),
|
|
82
|
+
maxCost: Type.Optional(Type.Number({ description: "Max cost budget in USD (default: unlimited)", minimum: 0.01 })),
|
|
82
83
|
}),
|
|
83
84
|
|
|
84
85
|
async execute(_toolCallId, params, signal, onUpdate, ctx) {
|
|
85
86
|
const details: ColonyDetails = { state: null, phase: "initializing", log: [] };
|
|
86
87
|
|
|
88
|
+
// Resolve models: use current session model for worker/soldier, find a cheap model for scout
|
|
89
|
+
const currentModel = ctx.model?.id;
|
|
90
|
+
const modelOverrides: Record<string, string> = {};
|
|
91
|
+
if (currentModel) {
|
|
92
|
+
modelOverrides.worker = currentModel;
|
|
93
|
+
modelOverrides.soldier = currentModel;
|
|
94
|
+
}
|
|
95
|
+
|
|
87
96
|
const emit = () => {
|
|
88
97
|
const summary = details.state
|
|
89
98
|
? `${statusIcon(details.state.status)} Colony: ${details.phase}`
|
|
@@ -126,6 +135,8 @@ For simple single-file tasks, work directly without the colony.`,
|
|
|
126
135
|
cwd: ctx.cwd,
|
|
127
136
|
goal: params.goal,
|
|
128
137
|
maxAnts: params.maxAnts,
|
|
138
|
+
maxCost: params.maxCost,
|
|
139
|
+
modelOverrides,
|
|
129
140
|
signal: signal ?? undefined,
|
|
130
141
|
callbacks,
|
|
131
142
|
});
|
|
@@ -140,6 +151,7 @@ For simple single-file tasks, work directly without the colony.`,
|
|
|
140
151
|
`**Goal:** ${state.goal}`,
|
|
141
152
|
`**Status:** ${statusIcon(state.status)} ${state.status}`,
|
|
142
153
|
`**Duration:** ${elapsed}`,
|
|
154
|
+
...(state.maxCost != null ? [`**Budget:** ${formatCost(m.totalCost)} / ${formatCost(state.maxCost)}`] : []),
|
|
143
155
|
``,
|
|
144
156
|
`### Metrics`,
|
|
145
157
|
`- Tasks: ${m.tasksDone}/${m.tasksTotal} done, ${m.tasksFailed} failed`,
|
|
@@ -165,7 +177,7 @@ For simple single-file tasks, work directly without the colony.`,
|
|
|
165
177
|
return {
|
|
166
178
|
content: [{ type: "text", text: report }],
|
|
167
179
|
details: { ...details },
|
|
168
|
-
isError: state.status === "failed",
|
|
180
|
+
isError: state.status === "failed" || state.status === "budget_exceeded",
|
|
169
181
|
};
|
|
170
182
|
} catch (e) {
|
|
171
183
|
return {
|
|
@@ -184,6 +196,7 @@ For simple single-file tasks, work directly without the colony.`,
|
|
|
184
196
|
const goal = args.goal?.length > 60 ? args.goal.slice(0, 57) + "..." : args.goal;
|
|
185
197
|
text += "\n " + theme.fg("dim", goal || "...");
|
|
186
198
|
if (args.maxAnts) text += theme.fg("muted", ` (max: ${args.maxAnts})`);
|
|
199
|
+
if (args.maxCost) text += theme.fg("warning", ` (budget: $${args.maxCost})`);
|
|
187
200
|
return new Text(text, 0, 0);
|
|
188
201
|
},
|
|
189
202
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import type {
|
|
16
16
|
ColonyState, Task, Ant, AntCaste, ColonyMetrics,
|
|
17
|
-
ConcurrencyConfig, TaskPriority,
|
|
17
|
+
ConcurrencyConfig, TaskPriority, ModelOverrides,
|
|
18
18
|
} from "./types.js";
|
|
19
19
|
import { DEFAULT_ANT_CONFIGS } from "./types.js";
|
|
20
20
|
import { Nest } from "./nest.js";
|
|
@@ -33,6 +33,8 @@ export interface QueenOptions {
|
|
|
33
33
|
cwd: string;
|
|
34
34
|
goal: string;
|
|
35
35
|
maxAnts?: number;
|
|
36
|
+
maxCost?: number;
|
|
37
|
+
modelOverrides?: ModelOverrides;
|
|
36
38
|
signal?: AbortSignal;
|
|
37
39
|
callbacks: QueenCallbacks;
|
|
38
40
|
}
|
|
@@ -138,8 +140,11 @@ async function runAntWave(
|
|
|
138
140
|
caste: AntCaste,
|
|
139
141
|
signal: AbortSignal | undefined,
|
|
140
142
|
callbacks: QueenCallbacks,
|
|
141
|
-
|
|
142
|
-
|
|
143
|
+
modelOverrides?: ModelOverrides,
|
|
144
|
+
maxCost?: number,
|
|
145
|
+
): Promise<"ok" | "budget_exceeded"> {
|
|
146
|
+
const config = { ...DEFAULT_ANT_CONFIGS[caste] };
|
|
147
|
+
if (modelOverrides?.[caste]) config.model = modelOverrides[caste];
|
|
143
148
|
|
|
144
149
|
let backoffMs = 0; // 429 退避时间
|
|
145
150
|
|
|
@@ -191,6 +196,15 @@ async function runAntWave(
|
|
|
191
196
|
|
|
192
197
|
// 调度循环:持续派蚂蚁直到没有待处理任务
|
|
193
198
|
while (!signal?.aborted) {
|
|
199
|
+
// Budget check
|
|
200
|
+
if (maxCost != null) {
|
|
201
|
+
const currentCost = nest.getState().ants.reduce((s, a) => s + a.usage.cost, 0);
|
|
202
|
+
if (currentCost >= maxCost) {
|
|
203
|
+
callbacks.onPhase("working", `Budget exceeded ($${currentCost.toFixed(3)} >= $${maxCost.toFixed(2)}). Stopping.`);
|
|
204
|
+
return "budget_exceeded";
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
194
208
|
const state = nest.getState();
|
|
195
209
|
const pending = state.tasks.filter(t => t.status === "pending" && t.caste === caste);
|
|
196
210
|
if (pending.length === 0) break;
|
|
@@ -254,6 +268,7 @@ async function runAntWave(
|
|
|
254
268
|
backoffMs = 0;
|
|
255
269
|
}
|
|
256
270
|
}
|
|
271
|
+
return "ok";
|
|
257
272
|
}
|
|
258
273
|
|
|
259
274
|
/**
|
|
@@ -276,6 +291,8 @@ export async function runColony(opts: QueenOptions): Promise<ColonyState> {
|
|
|
276
291
|
antsSpawned: 0, totalCost: 0, totalTokens: 0,
|
|
277
292
|
startTime: Date.now(), throughputHistory: [],
|
|
278
293
|
},
|
|
294
|
+
maxCost: opts.maxCost ?? null,
|
|
295
|
+
modelOverrides: opts.modelOverrides ?? {},
|
|
279
296
|
createdAt: Date.now(),
|
|
280
297
|
finishedAt: null,
|
|
281
298
|
};
|
|
@@ -286,11 +303,22 @@ export async function runColony(opts: QueenOptions): Promise<ColonyState> {
|
|
|
286
303
|
|
|
287
304
|
nest.init(initialState);
|
|
288
305
|
const { signal, callbacks } = opts;
|
|
306
|
+
const mo = opts.modelOverrides;
|
|
307
|
+
const mc = opts.maxCost;
|
|
308
|
+
|
|
309
|
+
const budgetStop = (phase: string) => {
|
|
310
|
+
nest.updateState({ status: "budget_exceeded", finishedAt: Date.now() });
|
|
311
|
+
callbacks.onPhase("budget_exceeded" as any, phase);
|
|
312
|
+
const s = nest.getState();
|
|
313
|
+
callbacks.onComplete(s);
|
|
314
|
+
return s;
|
|
315
|
+
};
|
|
289
316
|
|
|
290
317
|
try {
|
|
291
318
|
// ═══ Phase 1: 侦察 ═══
|
|
292
319
|
callbacks.onPhase("scouting", "Dispatching scout ants to explore codebase...");
|
|
293
|
-
await runAntWave(nest, opts.cwd, "scout", signal, callbacks)
|
|
320
|
+
if (await runAntWave(nest, opts.cwd, "scout", signal, callbacks, mo, mc) === "budget_exceeded")
|
|
321
|
+
return budgetStop("Budget exceeded during scouting");
|
|
294
322
|
|
|
295
323
|
// 检查侦察结果,如果没有产生工蚁任务,用侦察结果让女王自己拆
|
|
296
324
|
const postScout = nest.getAllTasks();
|
|
@@ -306,7 +334,8 @@ export async function runColony(opts: QueenOptions): Promise<ColonyState> {
|
|
|
306
334
|
// ═══ Phase 2: 工作 ═══
|
|
307
335
|
nest.updateState({ status: "working" });
|
|
308
336
|
callbacks.onPhase("working", `${workerTasks.length} tasks discovered. Dispatching worker ants...`);
|
|
309
|
-
await runAntWave(nest, opts.cwd, "worker", signal, callbacks)
|
|
337
|
+
if (await runAntWave(nest, opts.cwd, "worker", signal, callbacks, mo, mc) === "budget_exceeded")
|
|
338
|
+
return budgetStop("Budget exceeded during working");
|
|
310
339
|
|
|
311
340
|
// 处理工蚁产生的子任务(可能有多轮)
|
|
312
341
|
let rounds = 0;
|
|
@@ -317,7 +346,8 @@ export async function runColony(opts: QueenOptions): Promise<ColonyState> {
|
|
|
317
346
|
if (remaining.length === 0) break;
|
|
318
347
|
rounds++;
|
|
319
348
|
callbacks.onPhase("working", `Round ${rounds + 1}: ${remaining.length} sub-tasks from workers...`);
|
|
320
|
-
await runAntWave(nest, opts.cwd, "worker", signal, callbacks)
|
|
349
|
+
if (await runAntWave(nest, opts.cwd, "worker", signal, callbacks, mo, mc) === "budget_exceeded")
|
|
350
|
+
return budgetStop("Budget exceeded during sub-tasks");
|
|
321
351
|
}
|
|
322
352
|
|
|
323
353
|
// ═══ Phase 3: 审查 ═══
|
|
@@ -327,7 +357,8 @@ export async function runColony(opts: QueenOptions): Promise<ColonyState> {
|
|
|
327
357
|
callbacks.onPhase("reviewing", "Dispatching soldier ants to review changes...");
|
|
328
358
|
const reviewTask = makeReviewTask(completedWorkerTasks);
|
|
329
359
|
nest.writeTask(reviewTask);
|
|
330
|
-
await runAntWave(nest, opts.cwd, "soldier", signal, callbacks)
|
|
360
|
+
if (await runAntWave(nest, opts.cwd, "soldier", signal, callbacks, mo, mc) === "budget_exceeded")
|
|
361
|
+
return budgetStop("Budget exceeded during review");
|
|
331
362
|
|
|
332
363
|
// 兵蚁产生的修复任务
|
|
333
364
|
const fixTasks = nest.getAllTasks().filter(t =>
|
|
@@ -336,7 +367,8 @@ export async function runColony(opts: QueenOptions): Promise<ColonyState> {
|
|
|
336
367
|
if (fixTasks.length > 0) {
|
|
337
368
|
nest.updateState({ status: "working" });
|
|
338
369
|
callbacks.onPhase("working", `${fixTasks.length} fix tasks from review. Dispatching workers...`);
|
|
339
|
-
await runAntWave(nest, opts.cwd, "worker", signal, callbacks)
|
|
370
|
+
if (await runAntWave(nest, opts.cwd, "worker", signal, callbacks, mo, mc) === "budget_exceeded")
|
|
371
|
+
return budgetStop("Budget exceeded during fixes");
|
|
340
372
|
}
|
|
341
373
|
}
|
|
342
374
|
|
|
@@ -19,6 +19,9 @@ export const DEFAULT_ANT_CONFIGS: Record<AntCaste, Omit<AntConfig, "systemPrompt
|
|
|
19
19
|
soldier: { caste: "soldier", model: "claude-sonnet-4-5", tools: ["read", "bash", "grep", "find", "ls"], maxTurns: 8 },
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
+
/** Per-caste model overrides from user config */
|
|
23
|
+
export type ModelOverrides = Partial<Record<AntCaste, string>>;
|
|
24
|
+
|
|
22
25
|
// ═══ 任务 (Food Source) ═══
|
|
23
26
|
export type TaskStatus = "pending" | "claimed" | "active" | "done" | "failed" | "blocked";
|
|
24
27
|
export type TaskPriority = 1 | 2 | 3 | 4 | 5; // 1=highest
|
|
@@ -79,12 +82,14 @@ export interface Ant {
|
|
|
79
82
|
export interface ColonyState {
|
|
80
83
|
id: string;
|
|
81
84
|
goal: string;
|
|
82
|
-
status: "scouting" | "working" | "reviewing" | "done" | "failed";
|
|
85
|
+
status: "scouting" | "working" | "reviewing" | "done" | "failed" | "budget_exceeded";
|
|
83
86
|
tasks: Task[];
|
|
84
87
|
ants: Ant[];
|
|
85
88
|
pheromones: Pheromone[];
|
|
86
89
|
concurrency: ConcurrencyConfig;
|
|
87
90
|
metrics: ColonyMetrics;
|
|
91
|
+
maxCost: number | null; // cost budget in USD, null = unlimited
|
|
92
|
+
modelOverrides: ModelOverrides;
|
|
88
93
|
createdAt: number;
|
|
89
94
|
finishedAt: number | null;
|
|
90
95
|
}
|
|
@@ -75,13 +75,15 @@ export default function (pi: ExtensionAPI) {
|
|
|
75
75
|
|
|
76
76
|
const thinking = pi.getThinkingLevel();
|
|
77
77
|
const modelId = ctx.model?.id || "no-model";
|
|
78
|
-
const
|
|
78
|
+
const modelStr = theme.fg("accent", `◆ ${modelId}`);
|
|
79
79
|
|
|
80
80
|
const sep = theme.fg("dim", " | ");
|
|
81
|
-
const leftParts = [tokenStats, elapsed, cwdStr];
|
|
81
|
+
const leftParts = [modelStr, tokenStats, elapsed, cwdStr];
|
|
82
82
|
if (branchStr) leftParts.push(branchStr);
|
|
83
83
|
const left = leftParts.join(sep);
|
|
84
84
|
|
|
85
|
+
const right = theme.fg("dim", thinking);
|
|
86
|
+
|
|
85
87
|
const leftW = visibleWidth(left);
|
|
86
88
|
const rightW = visibleWidth(right);
|
|
87
89
|
const gap = width - leftW - rightW;
|