pitroom 0.10.1 → 0.12.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/.claude-plugin/plugin.json +3 -2
- package/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +21 -0
- package/README.md +11 -2
- package/dist/lib.mjs +25 -0
- package/dist/pitroom.mjs +379 -252
- package/dist/ui/app.js +1 -1
- package/gemini-context.md +5 -0
- package/gemini-extension.json +6 -0
- package/hooks/claude-hooks.json +16 -0
- package/hooks/hooks.json +1 -13
- package/package.json +3 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pitroom",
|
|
3
3
|
"description": "A free pit crew for your expensive coding agent: the superpowers development workflow, run by cheap workers. Delegate research, fixes, tests, reviews and whole plans from Claude Code, Codex or any agent to OpenCode, Codex or Claude Code workers, with receipts that prove the savings.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.12.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "TahaAtas"
|
|
7
7
|
},
|
|
@@ -18,5 +18,6 @@
|
|
|
18
18
|
"subagents",
|
|
19
19
|
"tokens",
|
|
20
20
|
"workers"
|
|
21
|
-
]
|
|
21
|
+
],
|
|
22
|
+
"hooks": "./hooks/claude-hooks.json"
|
|
22
23
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pitroom",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "A free pit crew for your expensive coding agent: delegate research, fixes, tests, reviews and parallel investigations to cheap worker agents running your own models, with verified answers, exact diffs and cost receipts.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "TahaAtas"
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.12.0
|
|
4
|
+
|
|
5
|
+
### Cooldowns
|
|
6
|
+
- A model that says "rate limited" (a free daily quota used up, an overloaded provider) is remembered for a while, so the next runs go straight to the fallback instead of each one trying the exhausted model first and waiting for it to fail. The wait comes from the provider's message when it gives one (`retry in 4h28m`), else a guess: 4 hours for a daily quota, 20 minutes for overload; at least a minute, at most a day.
|
|
7
|
+
- A model on cooldown is skipped only while another worker is left to run; if it is the only one it is still tried. Cooldowns expire on their own.
|
|
8
|
+
- The report says `skipped: … (cooling down until 14:05: …)`, the dashboard card shows "Skipped …", `pitroom doctor` warns with the time, and `pitroom cooldown` lists them (`--clear` tries them again). Only rate-limit failures count, not a missing model or a sign-in problem.
|
|
9
|
+
|
|
10
|
+
## 0.11.0
|
|
11
|
+
|
|
12
|
+
### Gemini CLI as your primary agent
|
|
13
|
+
- Pitroom installs into Gemini CLI as an extension: `gemini extensions install https://github.com/ATASTECH/pitroom` gives it the 14 skills and a short context file that introduces Pitroom (`gemini-extension.json`, `gemini-context.md`). Gemini CLI also still works as a worker (`-W gemini`); the two are separate. Gemini asks you to confirm the extension. Its session-start hook text did not reach a Gemini session in a test (Gemini probably runs extension hooks only once you trust them), so the context file is what introduces Pitroom there.
|
|
14
|
+
- `hooks/hooks.json` is now valid for both Claude Code and Gemini CLI (a Gemini extension reads that file too and warned about Claude Code's `PostToolUse` event on every session): it holds SessionStart only, with a command that fills `${CLAUDE_PLUGIN_ROOT}` in Claude Code and `${extensionPath}` in Gemini CLI. The card after each `pitroom` command is Claude Code's alone and moved to `hooks/claude-hooks.json`, named by `hooks` in the Claude plugin manifest. `npm run bump` and the release test keep `gemini-extension.json` in step with the version.
|
|
15
|
+
|
|
16
|
+
### Doctor
|
|
17
|
+
- Worker CLIs that are installed but not in your config now get a section ("Gemini CLI (installed, not in your config)") with how to use them, so a new worker is not invisible. They never count as warnings, and a CLI that is not installed stays out of the way.
|
|
18
|
+
- A Gemini API key that Gemini CLI keeps itself is no longer reported as "not signed in".
|
|
19
|
+
- Doctor warns when Pitroom is a Gemini extension and its skills are also linked into `~/.agents/skills`: Gemini would load them twice.
|
|
20
|
+
|
|
21
|
+
### Docs
|
|
22
|
+
- The README has a Gemini CLI install block and a row in the install table.
|
|
23
|
+
|
|
3
24
|
## 0.10.1
|
|
4
25
|
|
|
5
26
|
### Docs
|
package/README.md
CHANGED
|
@@ -260,7 +260,14 @@ codex plugin add pitroom@pitroom
|
|
|
260
260
|
npm i -g pitroom
|
|
261
261
|
```
|
|
262
262
|
|
|
263
|
-
**
|
|
263
|
+
**Gemini CLI**
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
gemini extensions install https://github.com/ATASTECH/pitroom
|
|
267
|
+
npm i -g pitroom
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Any other agent (Cursor, a plain shell) or just the CLI**
|
|
264
271
|
|
|
265
272
|
```bash
|
|
266
273
|
npm i -g pitroom
|
|
@@ -270,6 +277,7 @@ pitroom install
|
|
|
270
277
|
| Path | You get |
|
|
271
278
|
|---|---|
|
|
272
279
|
| Claude Code plugin | The 14 skills, the session-start hook that introduces Pitroom, and a card after each `pitroom` command. |
|
|
280
|
+
| Gemini CLI extension | The 14 skills and a short context file that introduces Pitroom (Gemini asks you to confirm the extension). Gemini CLI also works as a *worker*, which is separate: see [Workers](#workers). |
|
|
273
281
|
| Codex plugin | The 14 skills, a session-start hook that introduces Pitroom (so it is known even when Codex drops skill descriptions because many are installed), and a card after each `pitroom` command. Codex asks you to trust the plugin's hooks once. The hooks call `pitroom`, which comes from npm (`npm i -g pitroom`). |
|
|
274
282
|
| npm + `pitroom install` | The CLI, and the skills linked into `~/.agents/skills` and `~/.claude/skills`. |
|
|
275
283
|
|
|
@@ -449,6 +457,7 @@ pitroom crew [-i] [-g NAME] "task 1" "task 2" … (or --task-file with --- sep
|
|
|
449
457
|
pitroom run -i --plan PLAN --step N [--tier T] ["notes"]
|
|
450
458
|
pitroom review [run | --range A..B [--plan PLAN]] [--tier T | -W T] [--bg]
|
|
451
459
|
pitroom audit RUN [-W worker]
|
|
460
|
+
pitroom cooldown [--clear]
|
|
452
461
|
pitroom plan status PLAN [--json] · pitroom plan note PLAN "Task N: …"
|
|
453
462
|
pitroom status|wait|watch [run… | -g NAME] wait: --any --brief --timeout · watch: --json|--brief --interval
|
|
454
463
|
pitroom dash [--detach] [--port N] [--open] [--stop] a live page of the runs on 127.0.0.1
|
|
@@ -546,7 +555,7 @@ claude haiku low/medium/high/xhigh/max ? - -
|
|
|
546
555
|
|
|
547
556
|
Pitroom cannot know vendor prices and does not fetch them, so a cost is what you enter: `"costs": {"codex:gpt-6-sol": 1, "codex:gpt-6.1-sol": 2}` in the config, in any unit (they are only compared). `pitroom doctor` then prints the cost of the models in use and says when you priced a cheaper one of the same worker. A target that names only an effort (`codex:#low`) uses the model from `models`; a Codex or Claude Code worker with no pinned model gets a warning, because it would run the vendor's own default, which can change and cost more. `--effort LEVEL` sets the level for one run; your agent picks model and level from `pitroom models` (cheapest that fits: `low` for lookups, `medium` for ordinary changes, `high` for reviews).
|
|
548
557
|
|
|
549
|
-
Fallbacks cross backends (e.g. `"fallback": ["codex:#low", "opencode"]`): a worker that is rate-limited, logged out or missing its model hands the task to the next. Follow-ups (`--continue`) always stay on the worker that owns the session. Writing an adapter: [docs/backends.md](docs/backends.md).
|
|
558
|
+
Fallbacks cross backends (e.g. `"fallback": ["codex:#low", "opencode"]`): a worker that is rate-limited, logged out or missing its model hands the task to the next. Follow-ups (`--continue`) always stay on the worker that owns the session. Writing an adapter: [docs/backends.md](docs/backends.md). A model that says "rate limited" (a daily quota used up, an overloaded provider) is remembered for the time its message gives, or a guess: the next runs skip it while a fallback is left, so they do not each wait for it to fail. `pitroom cooldown` lists what is skipped and until when, `--clear` tries it again, and `doctor` shows it too.
|
|
550
559
|
|
|
551
560
|
---
|
|
552
561
|
|
package/dist/lib.mjs
CHANGED
|
@@ -774,6 +774,8 @@ function doctor3({ models, hasFallback }) {
|
|
|
774
774
|
const type = settings().security?.auth?.selectedType;
|
|
775
775
|
if (key || vertex) {
|
|
776
776
|
checks.push({ level: "ok", message: `Gemini CLI: ${key ? "an API key is set" : "Vertex AI is set up"}` });
|
|
777
|
+
} else if (type === "gemini-api-key" || type === "vertex-ai") {
|
|
778
|
+
checks.push({ level: "ok", message: `Gemini CLI: ${type === "vertex-ai" ? "Vertex AI" : "an API key"} is selected (kept by Gemini CLI)` });
|
|
777
779
|
} else if (signedIn && type === "oauth-personal") {
|
|
778
780
|
checks.push({
|
|
779
781
|
level: "warn",
|
|
@@ -1493,6 +1495,27 @@ function fill(template, values) {
|
|
|
1493
1495
|
return template.replace(/\{\{([A-Z_]+)\}\}/g, (_, key) => values[key]);
|
|
1494
1496
|
}
|
|
1495
1497
|
|
|
1498
|
+
// src/core/cooldown.ts
|
|
1499
|
+
var MAX_MS = 24 * 36e5;
|
|
1500
|
+
var OVERLOAD_MS = 20 * 6e4;
|
|
1501
|
+
var DAILY_MS = 4 * 36e5;
|
|
1502
|
+
function retryAfterMs(message) {
|
|
1503
|
+
const compact = /(?:retry|try again|resets?|available again)[^0-9]{0,24}((?:\d+(?:\.\d+)?\s*[dhms]\s*)+)/i.exec(message)?.[1];
|
|
1504
|
+
const words = /(?:retry|try again|resets?)[^0-9]{0,24}(\d+(?:\.\d+)?)\s*(second|minute|hour)s?/i.exec(message);
|
|
1505
|
+
let ms = 0;
|
|
1506
|
+
if (compact) {
|
|
1507
|
+
for (const [, n, unit] of compact.matchAll(/(\d+(?:\.\d+)?)\s*([dhms])/gi)) ms += Number(n) * { d: 864e5, h: 36e5, m: 6e4, s: 1e3 }[unit.toLowerCase()];
|
|
1508
|
+
} else if (words) {
|
|
1509
|
+
ms = Number(words[1]) * { second: 1e3, minute: 6e4, hour: 36e5 }[words[2].toLowerCase()];
|
|
1510
|
+
}
|
|
1511
|
+
return ms > 0 ? ms : void 0;
|
|
1512
|
+
}
|
|
1513
|
+
function cooldownMs(message) {
|
|
1514
|
+
const told = retryAfterMs(message);
|
|
1515
|
+
if (told !== void 0) return Math.min(Math.max(told, 6e4), MAX_MS);
|
|
1516
|
+
return /daily|per.?day|per day|exhausted your/i.test(message) ? DAILY_MS : OVERLOAD_MS;
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1496
1519
|
// src/core/answers.ts
|
|
1497
1520
|
var TASK_STATUSES = ["DONE", "DONE_WITH_CONCERNS", "NEEDS_CONTEXT", "BLOCKED"];
|
|
1498
1521
|
function parseStatus(text) {
|
|
@@ -1596,6 +1619,7 @@ export {
|
|
|
1596
1619
|
allBackends,
|
|
1597
1620
|
backendIds,
|
|
1598
1621
|
brief,
|
|
1622
|
+
cooldownMs,
|
|
1599
1623
|
describeTarget,
|
|
1600
1624
|
extractRefs,
|
|
1601
1625
|
fill,
|
|
@@ -1610,5 +1634,6 @@ export {
|
|
|
1610
1634
|
parseVerdict,
|
|
1611
1635
|
planName,
|
|
1612
1636
|
planTask,
|
|
1637
|
+
retryAfterMs,
|
|
1613
1638
|
verifyRefs
|
|
1614
1639
|
};
|