@irythill/orq 0.6.1 → 0.8.0
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.md +24 -17
- package/README.pt-BR.md +35 -18
- package/dist/agents.js +75 -2
- package/dist/commands/agent.js +173 -44
- package/dist/commands/board.js +1 -1
- package/dist/commands/claim.js +8 -1
- package/dist/commands/conductor.js +7 -6
- package/dist/commands/pick.js +16 -4
- package/dist/commands/rounds.js +3 -0
- package/dist/commands/setup.js +2 -6
- package/dist/commands/stats.js +2 -2
- package/dist/diagnose.js +3 -1
- package/dist/pick.js +73 -42
- package/dist/process.js +28 -7
- package/dist/rounds.js +40 -4
- package/dist/stats.js +55 -14
- package/package.json +4 -4
- package/skills/issue/SKILL.md +18 -7
package/README.md
CHANGED
|
@@ -48,9 +48,9 @@ You ── "/issue DEMO-123" ──► conductor (Claude, in any terminal)
|
|
|
48
48
|
| Agent | CLI | Possible roles | Notes |
|
|
49
49
|
|---|---|---|---|
|
|
50
50
|
| Claude Code | `claude` | conductor, implement, review | several accounts (`claude-accounts`); Opus as conductor |
|
|
51
|
-
| Codex | `codex` | implement, review | sandbox without network:
|
|
51
|
+
| Codex | `codex` | implement, review | sandbox without network: orq runs `git fetch` before a write run (`network = false`); quota from its session files (the free plan's 30-day window included) |
|
|
52
52
|
| OpenCode | `opencode` | implement, review | any provider (e.g. MiniMax); on MiniMax, quota from the Token Plan API with your key |
|
|
53
|
-
| Antigravity | `agy` | review | headless denies commands outside its allowlist: it reviews by reading the attached diff |
|
|
53
|
+
| Antigravity | `agy` | review (implement with an allowlist) | headless denies commands outside its allowlist: it reviews by reading the attached diff; it can't commit, so orq commits its write runs (`commit = false`) |
|
|
54
54
|
| GitHub Copilot | `copilot` | second opinion | small allowances on some plans: occasional use |
|
|
55
55
|
|
|
56
56
|
You declare only the ones you have, and the roles each may take.
|
|
@@ -58,7 +58,7 @@ You declare only the ones you have, and the roles each may take.
|
|
|
58
58
|
## Install
|
|
59
59
|
|
|
60
60
|
Linux, macOS or Windows (native, not only WSL), in any shell — bash, zsh, fish, PowerShell, cmd.
|
|
61
|
-
**Requirements:** Node
|
|
61
|
+
**Requirements:** Node 22+ with `npm`, `git`, and at least one agent from the table above, logged in. Optional:
|
|
62
62
|
[herdr](https://herdr.dev) or tmux, so each child gets its own tab or window (otherwise children run in the
|
|
63
63
|
background and `orq board` shows them).
|
|
64
64
|
|
|
@@ -100,7 +100,7 @@ git clone https://github.com/irythill/orq ~/Code/orq && cd ~/Code/orq
|
|
|
100
100
|
./install.sh # links in ~/.local/bin, herdr service, skills for Claude
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
Needs `git`, `jq`, Node
|
|
103
|
+
Needs `git`, `jq`, Node 22+ with `npm`, `python3` (3.11+ for TOML config; older → JSON config or
|
|
104
104
|
`pip install --user tomli`) and user `systemd` (WSL2: Ubuntu 22.04+ with systemd enabled). `install.sh` checks the
|
|
105
105
|
requirements (table of what's found and missing), builds the `orq` CLI (`src/` → `dist/`), then **symlinks** (never
|
|
106
106
|
copies) the scripts into `~/.local/bin`, `setup/herdr.service` into `~/.config/systemd/user/` (and enables it), and
|
|
@@ -120,10 +120,10 @@ Two layers, to keep **your way of working** apart from **the team's project**:
|
|
|
120
120
|
| File | Whose | What it holds |
|
|
121
121
|
|---|---|---|
|
|
122
122
|
| `~/.config/orq/config.toml` | yours, stays on your machine | agents, accounts, models per role and level, pick weights, memory limits |
|
|
123
|
-
| `<workspace>/.orq/workspace.toml`
|
|
123
|
+
| `<workspace>/.orq/workspace.toml` | the team's, versioned | Plane (projects, issue standard), repos, base branch, verification, tests, dependencies |
|
|
124
124
|
|
|
125
|
-
The more specific one wins, key by key. JSON works too (`config.json`). To see the merged result: `orq
|
|
126
|
-
(everything), `orq
|
|
125
|
+
The more specific one wins, key by key. JSON works too (`config.json`). To see the merged result: `orq config`
|
|
126
|
+
(everything), `orq config get policy.weights`, `orq config files`.
|
|
127
127
|
|
|
128
128
|
### Example: personal config
|
|
129
129
|
Complete, commented example: [`examples/irythill/config.toml`](examples/irythill/config.toml). The essentials:
|
|
@@ -135,7 +135,7 @@ roles = ["impl", "fix", "review"]
|
|
|
135
135
|
quota = ["codex"] # name in agent-quota's output
|
|
136
136
|
[agents.codex.models.impl]
|
|
137
137
|
simple = "gpt-6-sol@low" # model@effort, per issue level
|
|
138
|
-
medium = "gpt-6-sol@medium"
|
|
138
|
+
medium = ["gpt-6-sol@medium", "gpt-6-luna@medium"] # several: each (agent, model) pair is scored on its own history
|
|
139
139
|
heavy = "gpt-6.1-sol@high"
|
|
140
140
|
[agents.codex.models.review]
|
|
141
141
|
simple = "gpt-6-sol@low" # reviews scale with the issue too
|
|
@@ -155,6 +155,9 @@ run = "revtool --markdown -b {base}" # {base} = orq agent -b; it reads the
|
|
|
155
155
|
write = false
|
|
156
156
|
ok_exit = [0, 1] # exit 1 = findings, still a verdict
|
|
157
157
|
no_review = "Nothing to review" # matched on the answer's first line (or a short answer): not a verdict, status=fail
|
|
158
|
+
# commit = false # can't git commit: orq commits a write run's changes
|
|
159
|
+
# network = false # no network: orq fetches origin before a write run
|
|
160
|
+
# base_commit = false # can't review `-b <sha>` (default for a tool): pick skips it on a round delta, agent falls back to the branch base
|
|
158
161
|
# filter = "jq -r '...'" # optional: its output → [blocker]/[suggestion] lines
|
|
159
162
|
|
|
160
163
|
[conductor]
|
|
@@ -177,18 +180,19 @@ speed = 0.15
|
|
|
177
180
|
rotation = 0.20 # penalty for having been picked recently
|
|
178
181
|
```
|
|
179
182
|
|
|
180
|
-
### How `orq
|
|
181
|
-
1. **Filters:** only agents with that role, under the quota limit, not blocked (`orq
|
|
182
|
-
vendor other than the implementer's
|
|
183
|
+
### How `orq pick` chooses
|
|
184
|
+
1. **Filters:** only agents with that role whose CLI is on the PATH, under the quota limit, not blocked (`orq block`)
|
|
185
|
+
and, for reviews, from a vendor other than the implementer's (and, for a round's delta, able to review a commit:
|
|
186
|
+
`base_commit`). With several accounts, it prefers one whose pace stays within the limit, then
|
|
183
187
|
the least used.
|
|
184
188
|
2. **Scores:** `quality × delivery + tokens × economy + speed × quickness − rotation × recent picks`. The numbers come
|
|
185
|
-
from the history (`orq
|
|
189
|
+
from the history (`orq stats`); an agent with few runs uses the config's `prior` and gets an exploration bonus.
|
|
186
190
|
3. **`reserve = true` agents** (e.g. Claude, which shares quota with the conductor) only come in when nothing else fits.
|
|
187
191
|
|
|
188
192
|
```bash
|
|
189
|
-
orq
|
|
190
|
-
orq
|
|
191
|
-
orq
|
|
193
|
+
orq pick review --impl-agent codex --explain # every candidate's score and who was left out, and why
|
|
194
|
+
orq stats --days 30 # scoreboard per agent and model: delivery, approval, time (to the first turn), tokens
|
|
195
|
+
orq block antigravity --days 3 # out of the picks (e.g. weekly quota gone, no collector for it)
|
|
192
196
|
orq pick fix --same .orquestra/<ID>/impl-<repo>.pick # a fix round: the implementer's agent/model/account, effort +1
|
|
193
197
|
```
|
|
194
198
|
|
|
@@ -196,7 +200,7 @@ orq pick fix --same .orquestra/<ID>/impl-<repo>.pick # a fix round: the implem
|
|
|
196
200
|
orq speaks English and Portuguese: CLI messages, `orq board`, notices and `install.sh`. It follows
|
|
197
201
|
`[ui] lang` in your config (`"auto"` = system locale, `"en"`, `"pt"`), or the `ORQ_LANG` environment variable.
|
|
198
202
|
Switch it any time:
|
|
199
|
-
- `orq
|
|
203
|
+
- `orq lang pt` / `orq lang en` / `orq lang toggle` (`orq lang` alone shows the current one);
|
|
200
204
|
- `l` inside `orq board`;
|
|
201
205
|
- in herdr, a key for it: see [With herdr](#with-herdr).
|
|
202
206
|
|
|
@@ -213,7 +217,9 @@ Open the conductor in any terminal, in your workspace folder (the one `orq setup
|
|
|
213
217
|
```bash
|
|
214
218
|
cd ~/Code/<workspace> && orq conductor [account] [model] # any terminal: loads the conductor instructions, the workspace CLAUDE.md and the /issue skill
|
|
215
219
|
```
|
|
216
|
-
With several conductors, give each a fixed name (`export ORQ_CONDUCTOR_ID=<name
|
|
220
|
+
With several conductors, give each a fixed name (`export ORQ_CONDUCTOR_ID=<name>`; in herdr, the workspace label is
|
|
221
|
+
used) so `orq claim` can tell them apart: the Claude session is named `conductor-<workspace>:<name>`, and
|
|
222
|
+
`orq claim -l` ends each line with that `session=`, so conductors can message each other.
|
|
217
223
|
Variants:
|
|
218
224
|
- **herdr:** run `herdr` (the server runs as a service), then the same `orq conductor` in a pane (`herdr-conductor` still works).
|
|
219
225
|
- **tmux:** run `orq conductor` in a pane; children open as tmux windows.
|
|
@@ -299,6 +305,7 @@ Day to day, shortcuts and several issues at once: [docs/herdr.md](docs/herdr.md)
|
|
|
299
305
|
- [docs/omarchy.md](docs/omarchy.md) — extras for Omarchy users
|
|
300
306
|
- [docs/portability.md](docs/portability.md) — the roadmap: Linux, macOS and native Windows, any agent as conductor, user-defined roles, guided setup
|
|
301
307
|
- [CHANGELOG.md](CHANGELOG.md) — what changed, release by release
|
|
308
|
+
- [CONTRIBUTING.md](CONTRIBUTING.md) — branches, PR titles, how releases are cut
|
|
302
309
|
- `examples/` — real configurations to copy
|
|
303
310
|
|
|
304
311
|
## License
|
package/README.pt-BR.md
CHANGED
|
@@ -50,9 +50,9 @@ You ── "/issue DEMO-123" ──► conductor (Claude, in any terminal)
|
|
|
50
50
|
| Agente | CLI | Papéis possíveis | Observações |
|
|
51
51
|
|---|---|---|---|
|
|
52
52
|
| Claude Code | `claude` | conductor, implement, review | várias contas (`claude-accounts`); Opus como conductor |
|
|
53
|
-
| Codex | `codex` | implement, review | sandbox sem rede: o
|
|
53
|
+
| Codex | `codex` | implement, review | sandbox sem rede: o orq roda o `git fetch` antes de uma execução de escrita (`network = false`); cota lida dos arquivos de sessão (inclusive a janela de 30 dias do plano free) |
|
|
54
54
|
| OpenCode | `opencode` | implement, review | qualquer provider (ex.: MiniMax); na MiniMax, cota pela API do Token Plan com a sua chave |
|
|
55
|
-
| Antigravity | `agy` | review | em modo headless nega comandos fora da allowlist: faz a review lendo o diff anexado |
|
|
55
|
+
| Antigravity | `agy` | review (implement com allowlist) | em modo headless nega comandos fora da allowlist: faz a review lendo o diff anexado; não consegue commitar, então o orq commita as execuções de escrita dele (`commit = false`) |
|
|
56
56
|
| GitHub Copilot | `copilot` | segunda opinião | cota pequena em alguns planos: uso ocasional |
|
|
57
57
|
|
|
58
58
|
Você declara só os que tem, e os papéis que cada um pode assumir.
|
|
@@ -60,7 +60,7 @@ Você declara só os que tem, e os papéis que cada um pode assumir.
|
|
|
60
60
|
## Instalação
|
|
61
61
|
|
|
62
62
|
Linux, macOS ou Windows (nativo, não só WSL), em qualquer shell — bash, zsh, fish, PowerShell, cmd.
|
|
63
|
-
**Requisitos:** Node
|
|
63
|
+
**Requisitos:** Node 22+ com `npm`, `git`, e pelo menos um agente da tabela acima, logado. Opcional:
|
|
64
64
|
[herdr](https://herdr.dev) ou tmux, para cada filho ter sua própria aba ou janela (sem eles, os filhos rodam em
|
|
65
65
|
segundo plano e o `orq board` mostra todos).
|
|
66
66
|
|
|
@@ -103,7 +103,7 @@ git clone https://github.com/irythill/orq ~/Code/orq && cd ~/Code/orq
|
|
|
103
103
|
./install.sh # links em ~/.local/bin, serviço do herdr, skills do Claude
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
-
Precisa de `git`, `jq`, Node
|
|
106
|
+
Precisa de `git`, `jq`, Node 22+ com `npm`, `python3` (3.11+ para config em TOML; mais antigo → config em JSON ou
|
|
107
107
|
`pip install --user tomli`) e `systemd` de usuário (WSL2: Ubuntu 22.04+ com systemd habilitado). O `install.sh`
|
|
108
108
|
confere os requisitos (tabela do que foi encontrado e do que falta), compila o CLI `orq` (`src/` → `dist/`) e depois
|
|
109
109
|
cria **symlinks** (nunca copia) dos scripts em `~/.local/bin`, do `setup/herdr.service` em `~/.config/systemd/user/`
|
|
@@ -114,7 +114,7 @@ sobrescreve um arquivo de verdade (avisa e pula) e nunca escreve a sua config.
|
|
|
114
114
|
| Flag | O que faz |
|
|
115
115
|
|---|---|
|
|
116
116
|
| `--dry-run` | mostra o que faria, sem mudar nada |
|
|
117
|
-
| `--uninstall` | remove só os links que ele cria, e só os que apontam para este repo (config e histórico ficam
|
|
117
|
+
| `--uninstall` | remove só os links que ele cria, e só os que apontam para este repo, e desativa os timers de usuário do orq no systemd (`systemctl --user disable --now`); config e histórico ficam |
|
|
118
118
|
|
|
119
119
|
## Configuração
|
|
120
120
|
|
|
@@ -123,10 +123,10 @@ Duas camadas, para separar **o seu jeito de trabalhar** do **projeto do time**:
|
|
|
123
123
|
| Arquivo | De quem | O que guarda |
|
|
124
124
|
|---|---|---|
|
|
125
125
|
| `~/.config/orq/config.toml` | seu, fica na sua máquina | agentes, contas, modelos por papel e nível, pesos do pick, limites de memória |
|
|
126
|
-
| `<workspace>/.orq/workspace.toml`
|
|
126
|
+
| `<workspace>/.orq/workspace.toml` | do time, versionado | Plane (projetos, padrão de issue), repos, branch base, verificação, testes, dependências |
|
|
127
127
|
|
|
128
128
|
O mais específico ganha, chave por chave. JSON também funciona (`config.json`). Para ver o resultado mesclado:
|
|
129
|
-
`orq
|
|
129
|
+
`orq config` (tudo), `orq config get policy.weights`, `orq config files`.
|
|
130
130
|
|
|
131
131
|
### Exemplo: config pessoal
|
|
132
132
|
Exemplo completo e comentado: [`examples/irythill/config.toml`](examples/irythill/config.toml). O essencial:
|
|
@@ -138,7 +138,7 @@ roles = ["impl", "fix", "review"]
|
|
|
138
138
|
quota = ["codex"] # name in agent-quota's output
|
|
139
139
|
[agents.codex.models.impl]
|
|
140
140
|
simple = "gpt-6-sol@low" # model@effort, per issue level
|
|
141
|
-
medium = "gpt-6-sol@medium"
|
|
141
|
+
medium = ["gpt-6-sol@medium", "gpt-6-luna@medium"] # several: each (agent, model) pair is scored on its own history
|
|
142
142
|
heavy = "gpt-6.1-sol@high"
|
|
143
143
|
[agents.codex.models.review]
|
|
144
144
|
simple = "gpt-6-sol@low" # reviews scale with the issue too
|
|
@@ -151,6 +151,18 @@ roles = ["review"] # here it only reviews; for someone els
|
|
|
151
151
|
[agents.opencode.models.review]
|
|
152
152
|
default = "minimax/MiniMax-M3"
|
|
153
153
|
|
|
154
|
+
[agents.revtool] # a review tool, not a chat: no prompt, no session
|
|
155
|
+
vendor = "minimax" # the vendor of the model it runs, for the cross-vendor rule
|
|
156
|
+
roles = ["review"]
|
|
157
|
+
run = "revtool --markdown -b {base}" # {base} = orq agent -b; it reads the diff itself
|
|
158
|
+
write = false
|
|
159
|
+
ok_exit = [0, 1] # exit 1 = findings, still a verdict
|
|
160
|
+
no_review = "Nothing to review" # matched on the answer's first line (or a short answer): not a verdict, status=fail
|
|
161
|
+
# commit = false # can't git commit: orq commits a write run's changes
|
|
162
|
+
# network = false # no network: orq fetches origin before a write run
|
|
163
|
+
# base_commit = false # can't review `-b <sha>` (default for a tool): pick skips it on a round delta, agent falls back to the branch base
|
|
164
|
+
# filter = "jq -r '...'" # optional: its output → [blocker]/[suggestion] lines
|
|
165
|
+
|
|
154
166
|
[conductor]
|
|
155
167
|
handoff_at = 85 # % da janela → o orq handoff move o conductor para outra conta
|
|
156
168
|
max_per_account = 2 # conta que já tem esse tanto de conductors nunca é alvo do handoff
|
|
@@ -160,7 +172,8 @@ reset_grace_min = 15 # toda janela acima do gatilho renova d
|
|
|
160
172
|
issue_pattern = "(?<![a-z0-9])(?<issue>[a-z][a-z0-9]*-\\d+)(?![a-z0-9])" # Nome de branch/worktree → ID da issue, para `orq gc` e `orq ci` — padrão mostrado; regex, grupo nomeado `issue` (senão o grupo 1)
|
|
161
173
|
|
|
162
174
|
[policy]
|
|
163
|
-
|
|
175
|
+
quota_week = 95 # ≥ 95% of the week → agent out
|
|
176
|
+
quota_5h = { simple = 90, medium = 85, heavy = 80 } # same for the 5h window, by task level
|
|
164
177
|
pacing_penalty = 0.3 # score penalty when usage at the current pace would pass the pick limit (5h by level, week: quota_week) by the reset (0 = off)
|
|
165
178
|
# [agents.claude] headroom = 25 # points kept for conductors: children leave the account at limit − 25
|
|
166
179
|
[policy.weights]
|
|
@@ -170,18 +183,19 @@ speed = 0.15
|
|
|
170
183
|
rotation = 0.20 # penalty for having been picked recently
|
|
171
184
|
```
|
|
172
185
|
|
|
173
|
-
### Como o `orq
|
|
174
|
-
1. **Filtros:** só agentes com aquele papel, abaixo do limite de quota, não bloqueados
|
|
175
|
-
de um vendor diferente do implementador
|
|
186
|
+
### Como o `orq pick` escolhe
|
|
187
|
+
1. **Filtros:** só agentes com aquele papel cuja CLI está no PATH, abaixo do limite de quota, não bloqueados
|
|
188
|
+
(`orq block`) e, para reviews, de um vendor diferente do implementador (e, para o delta de uma rodada, capazes de
|
|
189
|
+
revisar um commit: `base_commit`). Com várias contas, prefere uma cujo ritmo fique dentro do limite e, como
|
|
176
190
|
desempate, a menos usada.
|
|
177
191
|
2. **Pontuação:** `quality × delivery + tokens × economy + speed × quickness − rotation × recent picks`. Os números vêm
|
|
178
|
-
do histórico (`orq
|
|
192
|
+
do histórico (`orq stats`); um agente com poucas execuções usa o `prior` da config e ganha um bônus de exploração.
|
|
179
193
|
3. **Agentes com `reserve = true`** (ex.: Claude, que divide quota com o conductor) só entram quando nada mais serve.
|
|
180
194
|
|
|
181
195
|
```bash
|
|
182
|
-
orq
|
|
183
|
-
orq
|
|
184
|
-
orq
|
|
196
|
+
orq pick review --impl-agent codex --explain # every candidate's score and who was left out, and why
|
|
197
|
+
orq stats --days 30 # scoreboard per agent and model: delivery, approval, time (to the first turn), tokens
|
|
198
|
+
orq block antigravity --days 3 # out of the picks (e.g. weekly quota gone, no collector for it)
|
|
185
199
|
orq pick fix --same .orquestra/<ID>/impl-<repo>.pick # a fix round: the implementer's agent/model/account, effort +1
|
|
186
200
|
```
|
|
187
201
|
|
|
@@ -189,7 +203,7 @@ orq pick fix --same .orquestra/<ID>/impl-<repo>.pick # a fix round: the implem
|
|
|
189
203
|
O orq fala inglês e português: mensagens da CLI, `orq board`, avisos e `install.sh`. Ele segue `[ui] lang` na sua
|
|
190
204
|
config (`"auto"` = idioma do sistema, `"en"`, `"pt"`) ou a variável de ambiente `ORQ_LANG`. Para trocar a qualquer
|
|
191
205
|
momento:
|
|
192
|
-
- `orq
|
|
206
|
+
- `orq lang pt` / `orq lang en` / `orq lang toggle` (`orq lang` sozinho mostra o atual);
|
|
193
207
|
- a tecla `l` dentro do `orq board`;
|
|
194
208
|
- no herdr, uma tecla para isso: veja [Com o herdr](#com-o-herdr).
|
|
195
209
|
|
|
@@ -205,7 +219,9 @@ Abra o conductor em qualquer terminal, na pasta do seu workspace (a que o `orq s
|
|
|
205
219
|
```bash
|
|
206
220
|
cd ~/Code/<workspace> && orq conductor [conta] [modelo] # qualquer terminal: carrega as instruções do conductor, o CLAUDE.md do workspace e a skill /issue
|
|
207
221
|
```
|
|
208
|
-
Com vários conductors, dê a cada um um nome fixo (`export ORQ_CONDUCTOR_ID=<nome
|
|
222
|
+
Com vários conductors, dê a cada um um nome fixo (`export ORQ_CONDUCTOR_ID=<nome>`; no herdr, vale o label do
|
|
223
|
+
workspace) para o `orq claim` distingui-los: a sessão do Claude se chama `conductor-<workspace>:<nome>`, e o
|
|
224
|
+
`orq claim -l` termina cada linha com esse `session=`, para os conductors conseguirem se falar.
|
|
209
225
|
Variantes:
|
|
210
226
|
- **herdr:** rode `herdr` (o servidor roda como serviço) e, num pane, o mesmo `orq conductor` (o `herdr-conductor` continua funcionando).
|
|
211
227
|
- **tmux:** rode `orq conductor` num pane; os filhos abrem como janelas do tmux.
|
|
@@ -293,6 +309,7 @@ Dia a dia, atalhos e várias issues ao mesmo tempo: [docs/pt-BR/herdr.md](docs/p
|
|
|
293
309
|
- [docs/pt-BR/omarchy.md](docs/pt-BR/omarchy.md) — extras para quem usa Omarchy
|
|
294
310
|
- [docs/pt-BR/portability.md](docs/pt-BR/portability.md) — o roadmap: Linux, macOS e Windows nativo, qualquer agente como conductor, papéis definidos pelo usuário, setup guiado
|
|
295
311
|
- [CHANGELOG.pt-BR.md](CHANGELOG.pt-BR.md) — o que mudou, versão a versão
|
|
312
|
+
- [CONTRIBUTING.md](CONTRIBUTING.md) — branches, títulos de PR, como sai uma versão (em inglês)
|
|
296
313
|
- `examples/` — configurações reais para copiar
|
|
297
314
|
|
|
298
315
|
## Licença
|
package/dist/agents.js
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
|
+
// AgentDef — how to run each agent, as command templates in the config. The five built-in agents below are defaults
|
|
2
|
+
// the user may override key by key in [agents.<name>]; any other CLI becomes usable by declaring `run` there.
|
|
3
|
+
//
|
|
4
|
+
// [agents.acme]
|
|
5
|
+
// run = "acme exec [--model {model}] --prompt-file {prompt} {mode}" # new session
|
|
6
|
+
// resume = "acme exec --resume {session} --prompt-file {prompt} {mode}" # follow-up (-R)
|
|
7
|
+
// readonly = "--sandbox read-only" # {mode} in read-only runs (-r); appended to `run` when it has no {mode}
|
|
8
|
+
// write = "--sandbox workspace-write" # {mode} otherwise; false = the agent only runs read only
|
|
9
|
+
// stdin = true # the prompt goes on stdin (else use {prompt} or {prompt_text})
|
|
10
|
+
// format = "text" # text (answer = stdout) | claude | codex | opencode | antigravity
|
|
11
|
+
// session = { from_log = "session: (\\S+)" } # or "uuid": orq makes one and passes it as {session}
|
|
12
|
+
// answer = "stdout" # stdout | file (the agent writes {out} itself)
|
|
13
|
+
// env = { ACME_NO_MCP = "1" }
|
|
14
|
+
// tui = "acme --on-turn-end {hook_cmd} {prompt_text}" # -T: the agent's own screen (new session)
|
|
15
|
+
// tui_resume = "acme --resume {session} --on-turn-end {hook_cmd} {prompt_text}" # -T -R with the screen closed
|
|
16
|
+
// ok_exit = [0, 1] # exit codes that still count as a verdict (a review tool exits 1 on findings)
|
|
17
|
+
// filter = "jq -r '.findings[] | ...'" # shell line: gets the answer on stdin, its stdout becomes the answer
|
|
18
|
+
// no_review = "Nothing to review" # regex: a match on the answer's first line (or a short answer, 200 chars) = nothing reviewed → status=fail
|
|
19
|
+
// commit = false # the agent can't run git commit: orq commits a write run's changes for it
|
|
20
|
+
// network = false # the agent has no network: orq fetches origin before a write run (no fetch/pull/push for it)
|
|
21
|
+
// base_commit = false # can't review `-b <commit>` (diffs against origin/<base> itself): pick skips it, agent falls back to the branch base (default: follows usesPrompt: true if the agent takes the prompt, false for a tool that ignores it)
|
|
22
|
+
//
|
|
23
|
+
// Templates: words split on spaces ('...' or "..." keep spaces). {name} or {name:default}; a [group] is dropped when
|
|
24
|
+
// any placeholder in it is empty, and repeated for a list placeholder ({gitroots}). Placeholders: prompt (file),
|
|
25
|
+
// prompt_text, prompt_hint, out (answer file), dir (where the agent runs), repo (-d), base (-b), model, effort, session, gitdir,
|
|
26
|
+
// gitroots, gitroots_json, opencode_config, title, mode; in tui templates also the end-of-turn hook as hook_cmd (a
|
|
27
|
+
// shell line), hook_json (an argv array, Codex's notify) and hook_settings (Claude's --settings).
|
|
28
|
+
// The hook (`orq agent --turn <job> <turn_hook>`) reads the turn in the agent's own shape: claude (Stop hook JSON on
|
|
29
|
+
// stdin), codex (notify JSON as the last argument), opencode (<session id> <answer file>, from orq's plugin) or text
|
|
30
|
+
// (the answer on stdin, the session id as an argument).
|
|
31
|
+
import { spawnSync } from "node:child_process";
|
|
32
|
+
import { existsSync } from "node:fs";
|
|
33
|
+
import { delimiter, join } from "node:path";
|
|
1
34
|
import { m } from "./i18n.js";
|
|
2
35
|
/** Does the agent's command take the prompt (stdin, a file in its folder or a {prompt*} placeholder)? A review tool like revtool does not. */
|
|
3
36
|
export const usesPrompt = (a) => Boolean(a.stdin || a.prompt_in_dir || /\{prompt(_text|_hint)?\}/.test(a.run ?? ""));
|
|
37
|
+
/** Can the agent review the delta from a commit (`-b <sha>`)? A tool that ignores the prompt diffs against origin/<base> itself, so by default it can't. */
|
|
38
|
+
export const baseCommit = (def) => def.base_commit ?? usesPrompt(def);
|
|
39
|
+
/** Does `base` name a commit rather than a branch (no origin/<base>, but it resolves)? A fix round's round-<n>.sha does. */
|
|
40
|
+
export function isCommitBase(repo, base) {
|
|
41
|
+
const has = (ref) => spawnSync("git", ["-C", repo, "rev-parse", "--verify", "-q", `${ref}^{commit}`]).status === 0;
|
|
42
|
+
return !has(`origin/${base}`) && has(base);
|
|
43
|
+
}
|
|
44
|
+
/** What orq does for a write run in a git repo that the agent itself can't: commit its changes, fetch origin. */
|
|
45
|
+
export const stepIns = (def, ro, inGit) => ({ commit: !ro && inGit && def.commit === false, fetch: !ro && inGit && def.network === false });
|
|
46
|
+
/** The note added to the prompt so the agent doesn't try what orq does for it. */
|
|
47
|
+
export function stepInNote(s) {
|
|
48
|
+
const l = [];
|
|
49
|
+
if (s.fetch)
|
|
50
|
+
l.push("- You have no network access. orq already ran `git fetch origin`, so the origin/* refs are fresh: rebase or diff against them locally. Don't run git fetch, pull or push.");
|
|
51
|
+
if (s.commit)
|
|
52
|
+
l.push("- You can't run `git commit`. Leave your changes in the working tree; orq commits them after you finish. Start your final answer with a one-line commit message in the form `Commit: <message>`.");
|
|
53
|
+
return l.length ? `\n\n## Environment (from orq)\n${l.join("\n")}\n` : "";
|
|
54
|
+
}
|
|
55
|
+
/** The commit message an agent proposed (`Commit: ...` line in its answer), else the fallback. */
|
|
56
|
+
export const commitMessage = (answer, fallback) => /^\W*commit:\s*`?([^`\n]+?)`?\s*$/im.exec(answer)?.[1]?.trim() || fallback;
|
|
4
57
|
/** Read only runs of a `throwaway` agent get a worktree copy of HEAD, but only where there is a git repo to copy. */
|
|
5
58
|
export const useThrowaway = (def, ro, resume, inGit) => Boolean(def.throwaway && ro && !resume && inGit);
|
|
6
59
|
const NOMCP_CODEX = "-c mcp_servers.plane.enabled=false -c mcp_servers.shadcn.enabled=false";
|
|
@@ -29,7 +82,7 @@ export const BUILTIN_AGENTS = {
|
|
|
29
82
|
`--skip-git-repo-check {mode} ${NOMCP_CODEX} -o {out} -`,
|
|
30
83
|
resume: `codex exec resume {session} -c model_reasoning_effort={effort:low} ` +
|
|
31
84
|
`-c sandbox_workspace_write.writable_roots={gitroots_json} ${NOMCP_CODEX} -o {out} -`,
|
|
32
|
-
readonly: "", write: "[--add-dir {gitroots}]", stdin: true, format: "codex", answer: "file", throwaway: true,
|
|
85
|
+
readonly: "", write: "[--add-dir {gitroots}]", stdin: true, format: "codex", answer: "file", throwaway: true, network: false,
|
|
33
86
|
// The screen: no approvals (nobody to approve), the same sandbox as exec; notify = end of turn.
|
|
34
87
|
tui: `codex [-m {model}] -c model_reasoning_effort={effort:low} -s workspace-write -a never -C {dir} {mode} ` +
|
|
35
88
|
`${NOMCP_CODEX} -c notify={hook_json} {prompt_text}`,
|
|
@@ -51,7 +104,7 @@ export const BUILTIN_AGENTS = {
|
|
|
51
104
|
// a run that only had commands denied still counts when the worktree changed (see the antigravity format). The prompt goes in a file in its folder (excluded from git) and -p only says "read it".
|
|
52
105
|
run: `${AGY} {mode} -p {prompt_hint}`, resume: `${AGY} --conversation {session} {mode} -p {prompt_hint}`,
|
|
53
106
|
readonly: "--mode plan", write: "--mode accept-edits --add-dir {gitdir}",
|
|
54
|
-
format: "antigravity", throwaway: true, prompt_in_dir: true,
|
|
107
|
+
format: "antigravity", throwaway: true, prompt_in_dir: true, commit: false,
|
|
55
108
|
},
|
|
56
109
|
copilot: {
|
|
57
110
|
// Second opinion, always read only: git reads allowed, anything else denied by -p without asking.
|
|
@@ -68,6 +121,26 @@ export function agentDef(cfg, name) {
|
|
|
68
121
|
throw new Error(m(`unknown agent: ${name} (built in: ${Object.keys(BUILTIN_AGENTS).join(", ")}; others need agents.${name}.run in the config)`, `agente desconhecido: ${name} (embutidos: ${Object.keys(BUILTIN_AGENTS).join(", ")}; outros precisam de agents.${name}.run no config)`));
|
|
69
122
|
return def;
|
|
70
123
|
}
|
|
124
|
+
/** Is `bin` on PATH? (PATHEXT on Windows: claude.cmd, codex.exe…) A path (with a slash) must exist itself. */
|
|
125
|
+
export function onPath(bin) {
|
|
126
|
+
if (/[\\/]/.test(bin))
|
|
127
|
+
return existsSync(bin);
|
|
128
|
+
const exts = process.platform === "win32" ? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT").split(";") : [""];
|
|
129
|
+
return (process.env.PATH ?? "").split(delimiter).some((d) => d && exts.some((e) => existsSync(join(d, bin + e))));
|
|
130
|
+
}
|
|
131
|
+
/** Why `name` can't start here (its CLI doesn't resolve on the PATH the child inherits), or undefined when it can. */
|
|
132
|
+
export function missingBinary(cfg, name) {
|
|
133
|
+
let bin;
|
|
134
|
+
try {
|
|
135
|
+
bin = tokenize(agentDef(cfg, name).run)[0]?.text;
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
if (!bin || onPath(bin))
|
|
141
|
+
return undefined;
|
|
142
|
+
return m(`\`${bin}\` not found on PATH (installed for another Node version? reinstall it)`, `\`${bin}\` não está no PATH (instalado para outra versão do Node? reinstale)`);
|
|
143
|
+
}
|
|
71
144
|
/** Split a template into words, remembering which [group] each belongs to. */
|
|
72
145
|
export function tokenize(t) {
|
|
73
146
|
const out = [];
|