agent-tank 0.9.6 → 0.9.8
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 +77 -34
- package/bin/agent-tank.js +61 -16
- package/package.json +5 -3
- package/src/activity-monitor.js +18 -7
- package/src/agents/agy.js +301 -0
- package/src/agents/base.js +27 -4
- package/src/agents/claude.js +39 -10
- package/src/agents/codex.js +1 -1
- package/src/agents/pty-output-parser.js +10 -4
- package/src/cli-background.js +198 -0
- package/src/client-auto-refresh-helpers.js +7 -7
- package/src/client-auto-refresh.js +2 -2
- package/src/client-monitor.js +2 -2
- package/src/discovery.js +9 -24
- package/src/history-store.js +1 -1
- package/src/icons.js +2 -2
- package/src/index.js +7 -6
- package/src/logger.js +2 -2
- package/src/pace-attachment.js +7 -7
- package/src/process-utils.js +215 -0
- package/src/public-status.js +5 -5
- package/src/snapshot-metrics.js +6 -6
- package/src/status-page.css +6 -6
- package/src/status-page.js +56 -38
- package/src/usage-formatters.js +7 -8
- package/src/agents/gemini-direct.js +0 -234
- package/src/agents/gemini.js +0 -463
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Agent Tank is a local dashboard and HTTP API for monitoring usage limits in AI c
|
|
|
7
7
|
It supports:
|
|
8
8
|
|
|
9
9
|
- Claude Code
|
|
10
|
-
-
|
|
10
|
+
- Antigravity CLI
|
|
11
11
|
- OpenAI Codex
|
|
12
12
|
|
|
13
13
|
## How It Gets the Data
|
|
@@ -17,7 +17,7 @@ This is the part that matters.
|
|
|
17
17
|
Agent Tank reads usage directly from the local CLI tools you already use. It launches the installed CLIs locally, runs their built-in usage commands, and parses the output into a unified web UI and JSON API.
|
|
18
18
|
|
|
19
19
|
- Claude: runs `/usage`
|
|
20
|
-
-
|
|
20
|
+
- Antigravity: runs `/usage`
|
|
21
21
|
- Codex: prefers JSON-RPC `account/rateLimits/read`, falls back to `/status`
|
|
22
22
|
|
|
23
23
|
What it does not do:
|
|
@@ -37,7 +37,7 @@ Agent Tank is meant for subscription-based coding agent products where the CLI i
|
|
|
37
37
|
Examples:
|
|
38
38
|
|
|
39
39
|
- Claude Code Pro / Max
|
|
40
|
-
-
|
|
40
|
+
- Antigravity CLI with supported subscription plans
|
|
41
41
|
- ChatGPT Codex with supported plans
|
|
42
42
|
|
|
43
43
|
It is not for:
|
|
@@ -62,6 +62,47 @@ Or run it directly:
|
|
|
62
62
|
npx agent-tank
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
### Run from Source
|
|
66
|
+
|
|
67
|
+
If you want to run the latest code from a checkout instead of the published package:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# 1. Clone the repo
|
|
71
|
+
git clone https://github.com/integry/agent-tank.git
|
|
72
|
+
cd agent-tank
|
|
73
|
+
|
|
74
|
+
# 2. Install dependencies (compiles node-pty natively)
|
|
75
|
+
npm install
|
|
76
|
+
|
|
77
|
+
# 3. Run it
|
|
78
|
+
npm start # = node bin/agent-tank.js
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
By default it auto-discovers installed CLIs and serves the dashboard + API at `http://127.0.0.1:3456`.
|
|
82
|
+
|
|
83
|
+
To pass flags, call the entry point directly (`npm start` does not forward arguments cleanly):
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
node bin/agent-tank.js --claude --codex --port 8080
|
|
87
|
+
node bin/agent-tank.js --once --json # one-shot, prints JSON, no server
|
|
88
|
+
node bin/agent-tank.js --no-docker # localhost only
|
|
89
|
+
node bin/agent-tank.js --help # full option list
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Prerequisites:
|
|
93
|
+
|
|
94
|
+
- **Node.js 18+**
|
|
95
|
+
- `node-pty` is a native module, so `npm install` needs **Python 3.8+** and **C/C++ build tools**. See [Installation Notes](#installation-notes) if the build fails.
|
|
96
|
+
- At least one supported CLI installed and authenticated on your `PATH` (`claude`, `agy`, or `codex`).
|
|
97
|
+
|
|
98
|
+
Other useful scripts:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm test # run all tests
|
|
102
|
+
npm run lint # check code style
|
|
103
|
+
npm run rebuild # rebuild node-pty against a detected Python
|
|
104
|
+
```
|
|
105
|
+
|
|
65
106
|
### First Run
|
|
66
107
|
|
|
67
108
|
```bash
|
|
@@ -87,14 +128,14 @@ agent-tank --no-docker
|
|
|
87
128
|
|
|
88
129
|
```bash
|
|
89
130
|
# Monitor only specific agents
|
|
90
|
-
agent-tank --claude --
|
|
91
|
-
|
|
92
|
-
# Prefer direct Gemini quota fetching
|
|
93
|
-
agent-tank --gemini --gemini-mode direct
|
|
131
|
+
agent-tank --claude --agy
|
|
94
132
|
|
|
95
133
|
# Use a custom port
|
|
96
134
|
agent-tank --port 8080
|
|
97
135
|
|
|
136
|
+
# Keep Agent Tank running after closing this terminal
|
|
137
|
+
agent-tank --background
|
|
138
|
+
|
|
98
139
|
# Fetch once and print JSON
|
|
99
140
|
agent-tank --once --json
|
|
100
141
|
|
|
@@ -130,7 +171,7 @@ agent-tank --refresh-cooldown 60
|
|
|
130
171
|
| Agent | Method | Metrics |
|
|
131
172
|
|---|---|---|
|
|
132
173
|
| Claude | PTY `/usage` or Anthropic OAuth API | Current session, weekly all-models, weekly Sonnet-only |
|
|
133
|
-
|
|
|
174
|
+
| Antigravity | PTY `/usage` | Per-model quota availability and reset windows when reported |
|
|
134
175
|
| Codex | JSON-RPC preferred, PTY fallback | 5-hour limits, weekly limits, model/account info |
|
|
135
176
|
|
|
136
177
|
## Basic Usage
|
|
@@ -153,6 +194,14 @@ agent-tank --claude --codex
|
|
|
153
194
|
agent-tank --once --json
|
|
154
195
|
```
|
|
155
196
|
|
|
197
|
+
### Background Server Mode
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
agent-tank --background
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
This starts Agent Tank as a detached process, prints the background PID, and exits the parent command.
|
|
204
|
+
|
|
156
205
|
### Bind to a Different Host or Port
|
|
157
206
|
|
|
158
207
|
```bash
|
|
@@ -186,9 +235,8 @@ Set it to `0` to disable the cooldown entirely.
|
|
|
186
235
|
```text
|
|
187
236
|
Options:
|
|
188
237
|
--claude Enable Claude monitoring
|
|
189
|
-
--
|
|
238
|
+
--agy Enable Antigravity monitoring
|
|
190
239
|
--codex Enable Codex monitoring
|
|
191
|
-
--gemini-mode <mode> Gemini strategy: fallback, direct, pty (default: fallback)
|
|
192
240
|
--port <port> HTTP server port (default: 3456)
|
|
193
241
|
--host <host> Bind address (default: 127.0.0.1 + Docker bridge when available)
|
|
194
242
|
--docker Enable Docker bridge bind when --host is omitted (default: true)
|
|
@@ -202,14 +250,15 @@ Options:
|
|
|
202
250
|
--auto-discover Auto-discover available agents (default: true)
|
|
203
251
|
--auto-refresh Enable/disable background auto-refresh (default: true)
|
|
204
252
|
--auto-refresh-mode <mode> Refresh mode: none, interval, activity (default: activity)
|
|
205
|
-
--auto-refresh-interval <seconds> Auto-refresh interval in seconds (default: 60)
|
|
253
|
+
--auto-refresh-interval <seconds> Auto-refresh interval in seconds (default: 60, 0 = disabled)
|
|
206
254
|
--refresh-cooldown <seconds> Minimum time between refreshes per agent (default: 30, 0 = disabled)
|
|
207
255
|
--activity-debounce <ms> Activity debounce interval in milliseconds (default: 5000)
|
|
208
256
|
--keepalive Enable/disable session keepalive (default: true)
|
|
209
|
-
--keepalive-interval <seconds> Session keepalive interval in seconds (default: 300)
|
|
257
|
+
--keepalive-interval <seconds> Session keepalive interval in seconds (default: 300, 0 = disabled)
|
|
210
258
|
--history-retention-days <days> Days to retain usage history (default: 14)
|
|
211
259
|
--once Fetch usage once and exit (no HTTP server)
|
|
212
260
|
--json Output pure JSON (suppress logging, use with --once)
|
|
261
|
+
--background Start Agent Tank as a detached background process
|
|
213
262
|
--help, -h Show this help message
|
|
214
263
|
```
|
|
215
264
|
|
|
@@ -217,7 +266,9 @@ Options:
|
|
|
217
266
|
|
|
218
267
|
### Environment Variables
|
|
219
268
|
|
|
220
|
-
Environment variables override CLI flags and config file values.
|
|
269
|
+
Environment variables override CLI flags and config file values. Background mode has
|
|
270
|
+
three exceptions: `--no-background`, `--once`, and `--json` suppress
|
|
271
|
+
`AGENT_TANK_BACKGROUND=1` for that run.
|
|
221
272
|
|
|
222
273
|
| Variable | Description |
|
|
223
274
|
|---|---|
|
|
@@ -228,7 +279,6 @@ Environment variables override CLI flags and config file values.
|
|
|
228
279
|
| `AGENT_TANK_DOCKER` | Enable/disable Docker bridge bind when `--host` is omitted |
|
|
229
280
|
| `AGENT_TANK_FRESH_PROCESS` | Use fresh process per refresh (`1`/`true`) |
|
|
230
281
|
| `AGENT_TANK_CLAUDE_API` | Use Claude API mode (`1`/`true`) |
|
|
231
|
-
| `AGENT_TANK_GEMINI_MODE` | Gemini strategy: `fallback`, `direct`, or `pty` |
|
|
232
282
|
| `AGENT_TANK_AUTO_REFRESH` | Enable/disable auto-refresh |
|
|
233
283
|
| `AGENT_TANK_AUTO_REFRESH_MODE` | `none`, `interval`, or `activity` |
|
|
234
284
|
| `AGENT_TANK_AUTO_REFRESH_INTERVAL` | Auto-refresh interval in seconds |
|
|
@@ -237,18 +287,20 @@ Environment variables override CLI flags and config file values.
|
|
|
237
287
|
| `AGENT_TANK_KEEPALIVE` | Enable/disable keepalive |
|
|
238
288
|
| `AGENT_TANK_KEEPALIVE_INTERVAL` | Keepalive interval in seconds |
|
|
239
289
|
| `AGENT_TANK_HISTORY_RETENTION_DAYS` | History retention window |
|
|
290
|
+
| `AGENT_TANK_BACKGROUND` | Start as a detached background process (`1`/`true`) |
|
|
291
|
+
| `AGENT_TANK_BACKGROUND_LOG` | Background child stdout/stderr log path (defaults to a temp file) |
|
|
292
|
+
| `AGENT_TANK_BACKGROUND_GRACE_MS` | Parent startup grace period before reporting background success; success means the child survived this period |
|
|
240
293
|
|
|
241
294
|
### Config File
|
|
242
295
|
|
|
243
296
|
```json
|
|
244
297
|
{
|
|
245
298
|
"claude": true,
|
|
246
|
-
"
|
|
299
|
+
"agy": true,
|
|
247
300
|
"codex": false,
|
|
248
301
|
"port": 8080,
|
|
249
302
|
"dockerAccess": true,
|
|
250
303
|
"claudeApi": false,
|
|
251
|
-
"geminiMode": "fallback",
|
|
252
304
|
"refreshCooldown": 30,
|
|
253
305
|
"autoRefresh": {
|
|
254
306
|
"mode": "activity",
|
|
@@ -272,26 +324,17 @@ Run with:
|
|
|
272
324
|
agent-tank -c config.json
|
|
273
325
|
```
|
|
274
326
|
|
|
275
|
-
##
|
|
276
|
-
|
|
277
|
-
By default, Gemini runs in `fallback` mode:
|
|
278
|
-
|
|
279
|
-
- try a direct quota fetch using the local Gemini OAuth session
|
|
280
|
-
- fall back to PTY `/stats` if the direct path fails
|
|
281
|
-
|
|
282
|
-
Available modes:
|
|
327
|
+
## Antigravity
|
|
283
328
|
|
|
284
|
-
|
|
285
|
-
- `direct`: use the direct quota API only
|
|
286
|
-
- `pty`: use interactive Gemini CLI `/stats` only
|
|
329
|
+
Antigravity support uses the `agy` CLI and reads the interactive `/usage` output.
|
|
287
330
|
|
|
288
331
|
In `--once` mode, Agent Tank prints the result and exits immediately after the output is flushed.
|
|
289
332
|
|
|
290
333
|
Examples:
|
|
291
334
|
|
|
292
335
|
```bash
|
|
293
|
-
agent-tank --
|
|
294
|
-
agent-tank --
|
|
336
|
+
agent-tank --agy
|
|
337
|
+
agent-tank --agy --once --json
|
|
295
338
|
```
|
|
296
339
|
|
|
297
340
|
## HTTP API
|
|
@@ -421,7 +464,7 @@ In activity mode, Agent Tank watches common local directories:
|
|
|
421
464
|
|
|
422
465
|
- Claude: `~/.config/claude/projects/`, `~/.claude/`
|
|
423
466
|
- Codex: `~/.codex/sessions/`, `~/.codex/`
|
|
424
|
-
-
|
|
467
|
+
- Antigravity: `~/.gemini/antigravity-cli/`
|
|
425
468
|
|
|
426
469
|
If no suitable directories are found, it falls back to interval mode.
|
|
427
470
|
|
|
@@ -509,15 +552,15 @@ You need at least one supported CLI installed and authenticated.
|
|
|
509
552
|
|
|
510
553
|
- [Claude Code](https://claude.ai/download) as `claude`
|
|
511
554
|
- Version 2.0+ required for `/usage`
|
|
512
|
-
-
|
|
513
|
-
-
|
|
555
|
+
- Antigravity CLI as `agy`
|
|
556
|
+
- `/usage` command support required
|
|
514
557
|
- OpenAI Codex as `codex`
|
|
515
558
|
|
|
516
559
|
Useful checks:
|
|
517
560
|
|
|
518
561
|
```bash
|
|
519
562
|
claude --version
|
|
520
|
-
|
|
563
|
+
agy --version
|
|
521
564
|
codex --version
|
|
522
565
|
```
|
|
523
566
|
|
|
@@ -527,7 +570,7 @@ codex --version
|
|
|
527
570
|
const { AgentTank } = require('agent-tank');
|
|
528
571
|
|
|
529
572
|
const watcher = new AgentTank({
|
|
530
|
-
agents: ['claude', '
|
|
573
|
+
agents: ['claude', 'agy'],
|
|
531
574
|
port: 3456,
|
|
532
575
|
autoDiscover: true
|
|
533
576
|
});
|
package/bin/agent-tank.js
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/* eslint-disable complexity */
|
|
2
|
+
/* eslint-disable complexity -- CLI option merging is centralized here to preserve precedence behavior. */
|
|
3
|
+
/* eslint-disable max-lines -- Tracked in issue #90; CLI help text and option precedence stay together for now. */
|
|
3
4
|
|
|
4
5
|
const { parseArgs } = require('node:util');
|
|
5
|
-
const {
|
|
6
|
-
|
|
6
|
+
const {
|
|
7
|
+
isTruthyEnv,
|
|
8
|
+
} = require('../src/process-utils.js');
|
|
9
|
+
const {
|
|
10
|
+
spawnBackgroundProcess,
|
|
11
|
+
warnAboutRunningProcesses,
|
|
12
|
+
} = require('../src/cli-background.js');
|
|
7
13
|
const pkg = require('../package.json');
|
|
8
14
|
|
|
9
15
|
const options = {
|
|
10
16
|
claude: { type: 'boolean', default: false },
|
|
11
|
-
|
|
17
|
+
agy: { type: 'boolean', default: false },
|
|
12
18
|
codex: { type: 'boolean', default: false },
|
|
13
19
|
'claude-api': { type: 'boolean', default: false },
|
|
14
|
-
'gemini-mode': { type: 'string' },
|
|
15
20
|
port: { type: 'string', default: '3456' },
|
|
16
21
|
host: { type: 'string' },
|
|
17
22
|
docker: { type: 'boolean', default: true },
|
|
@@ -33,9 +38,15 @@ const options = {
|
|
|
33
38
|
'keepalive-interval': { type: 'string', default: '300' },
|
|
34
39
|
once: { type: 'boolean', default: false },
|
|
35
40
|
json: { type: 'boolean', default: false },
|
|
41
|
+
background: { type: 'boolean', default: false },
|
|
36
42
|
};
|
|
37
43
|
|
|
38
|
-
const { values } = parseArgs({
|
|
44
|
+
const { values, tokens } = parseArgs({
|
|
45
|
+
options,
|
|
46
|
+
allowPositionals: false,
|
|
47
|
+
allowNegative: true,
|
|
48
|
+
tokens: true,
|
|
49
|
+
});
|
|
39
50
|
|
|
40
51
|
function exitWithCode(code, message, stream = process.stderr) {
|
|
41
52
|
if (message) {
|
|
@@ -63,10 +74,9 @@ Usage: agent-tank [options]
|
|
|
63
74
|
|
|
64
75
|
Options:
|
|
65
76
|
--claude Enable Claude monitoring
|
|
66
|
-
--
|
|
77
|
+
--agy Enable Antigravity monitoring
|
|
67
78
|
--codex Enable Codex monitoring
|
|
68
79
|
--claude-api Use direct Anthropic API for Claude usage (faster, 60s refresh)
|
|
69
|
-
--gemini-mode <mode> Gemini strategy: fallback, direct, pty (default: fallback)
|
|
70
80
|
--port <port> HTTP server port (default: 3456)
|
|
71
81
|
--host <host> Bind address (default: 127.0.0.1 + Docker bridge when available)
|
|
72
82
|
--docker Enable Docker bridge bind when --host is omitted (default: true)
|
|
@@ -87,6 +97,7 @@ Options:
|
|
|
87
97
|
--history-retention-days <days> Days to retain usage history (default: 14)
|
|
88
98
|
--once Fetch usage once and exit (no HTTP server)
|
|
89
99
|
--json Output pure JSON (suppress logging, use with --once)
|
|
100
|
+
--background Start Agent Tank as a detached background process
|
|
90
101
|
--help, -h Show this help message
|
|
91
102
|
|
|
92
103
|
Auto-Refresh Modes:
|
|
@@ -103,7 +114,6 @@ Environment variables:
|
|
|
103
114
|
AGENT_TANK_DOCKER Enable/disable Docker bridge bind ("1"/"true" or "0"/"false")
|
|
104
115
|
AGENT_TANK_FRESH_PROCESS Use fresh process per refresh ("1" or "true")
|
|
105
116
|
AGENT_TANK_CLAUDE_API Use direct Anthropic API for Claude usage ("1" or "true")
|
|
106
|
-
AGENT_TANK_GEMINI_MODE Gemini strategy: fallback, direct, pty
|
|
107
117
|
AGENT_TANK_AUTO_REFRESH Enable/disable background auto-refresh ("1" or "true" / "0" or "false")
|
|
108
118
|
AGENT_TANK_AUTO_REFRESH_MODE Refresh mode: none, interval, activity
|
|
109
119
|
AGENT_TANK_AUTO_REFRESH_INTERVAL Auto-refresh interval in seconds
|
|
@@ -112,14 +122,18 @@ Environment variables:
|
|
|
112
122
|
AGENT_TANK_KEEPALIVE Enable/disable session keepalive ("1" or "true" / "0" or "false")
|
|
113
123
|
AGENT_TANK_KEEPALIVE_INTERVAL Session keepalive interval in seconds
|
|
114
124
|
AGENT_TANK_HISTORY_RETENTION_DAYS Days to retain usage history
|
|
125
|
+
AGENT_TANK_BACKGROUND Start as a detached background process ("1" or "true")
|
|
126
|
+
AGENT_TANK_BACKGROUND_LOG Log file for background child stdout/stderr
|
|
127
|
+
AGENT_TANK_BACKGROUND_GRACE_MS Parent startup grace period before reporting background success
|
|
128
|
+
(success means the child survived this period)
|
|
115
129
|
|
|
116
130
|
Examples:
|
|
117
131
|
agent-tank # Auto-discover and monitor all available
|
|
118
|
-
agent-tank --
|
|
132
|
+
agent-tank --background # Start in the background and print the PID
|
|
133
|
+
agent-tank --claude --agy # Monitor specific agents
|
|
119
134
|
agent-tank --port 8080 # Use custom port
|
|
120
135
|
agent-tank --host 0.0.0.0 # Expose on all interfaces
|
|
121
136
|
agent-tank --no-docker # Bind localhost only when host is omitted
|
|
122
|
-
agent-tank --gemini-mode direct # Prefer direct Gemini quota API calls
|
|
123
137
|
agent-tank --auth-user admin --auth-pass secret # Enable basic auth
|
|
124
138
|
agent-tank --auth-token mykey # Enable API key auth
|
|
125
139
|
agent-tank -c ./config.json # Use config file
|
|
@@ -160,6 +174,37 @@ async function main() {
|
|
|
160
174
|
return;
|
|
161
175
|
}
|
|
162
176
|
|
|
177
|
+
const explicitNoBackground = tokens.some(token =>
|
|
178
|
+
token.kind === 'option' &&
|
|
179
|
+
token.name === 'background' &&
|
|
180
|
+
token.rawName === '--no-background');
|
|
181
|
+
const explicitBackground = tokens.some(token =>
|
|
182
|
+
token.kind === 'option' &&
|
|
183
|
+
token.name === 'background' &&
|
|
184
|
+
token.rawName === '--background');
|
|
185
|
+
const envBackgroundRequested = isTruthyEnv(process.env.AGENT_TANK_BACKGROUND) &&
|
|
186
|
+
!explicitNoBackground &&
|
|
187
|
+
!values.once &&
|
|
188
|
+
!values.json;
|
|
189
|
+
const backgroundRequested = explicitBackground || envBackgroundRequested;
|
|
190
|
+
const backgroundChild = isTruthyEnv(process.env.AGENT_TANK_BACKGROUND_CHILD);
|
|
191
|
+
|
|
192
|
+
if (backgroundRequested && !backgroundChild) {
|
|
193
|
+
for (const incompatibleFlag of ['once', 'json']) {
|
|
194
|
+
if (values[incompatibleFlag]) {
|
|
195
|
+
exitWithCode(1, `Error: --background cannot be combined with --${incompatibleFlag}`);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const started = await spawnBackgroundProcess();
|
|
201
|
+
process.exitCode = started ? 0 : 1;
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const { AgentTank } = require('../src/index.js');
|
|
206
|
+
const { installShutdownHandlers } = require('../src/shutdown-handler.js');
|
|
207
|
+
|
|
163
208
|
// Load config file if specified
|
|
164
209
|
let config = {};
|
|
165
210
|
if (values.config) {
|
|
@@ -174,7 +219,7 @@ async function main() {
|
|
|
174
219
|
// Merge CLI options with config (env vars > CLI flags > config file)
|
|
175
220
|
const agents = [];
|
|
176
221
|
if (values.claude || config.claude) agents.push('claude');
|
|
177
|
-
if (values.
|
|
222
|
+
if (values.agy || config.agy) agents.push('agy');
|
|
178
223
|
if (values.codex || config.codex) agents.push('codex');
|
|
179
224
|
|
|
180
225
|
const auth = {
|
|
@@ -203,9 +248,6 @@ async function main() {
|
|
|
203
248
|
config.claudeApi ||
|
|
204
249
|
claudeApiEnv === '1' || claudeApiEnv === 'true';
|
|
205
250
|
|
|
206
|
-
const geminiModeEnv = process.env.AGENT_TANK_GEMINI_MODE;
|
|
207
|
-
const geminiMode = geminiModeEnv || values['gemini-mode'] || config.geminiMode || 'fallback';
|
|
208
|
-
|
|
209
251
|
// Auto-refresh configuration (env > CLI > config file)
|
|
210
252
|
const autoRefreshEnv = process.env.AGENT_TANK_AUTO_REFRESH;
|
|
211
253
|
let autoRefreshEnabled = values['auto-refresh'];
|
|
@@ -298,7 +340,6 @@ async function main() {
|
|
|
298
340
|
auth,
|
|
299
341
|
freshProcess,
|
|
300
342
|
claudeApi,
|
|
301
|
-
geminiMode,
|
|
302
343
|
autoRefreshEnabled: onceMode ? false : autoRefreshEnabled, // Disable auto-refresh in one-shot mode
|
|
303
344
|
autoRefreshInterval,
|
|
304
345
|
autoRefreshMode: onceMode ? 'none' : autoRefreshMode, // Disable auto-refresh in one-shot mode
|
|
@@ -354,7 +395,11 @@ async function main() {
|
|
|
354
395
|
}
|
|
355
396
|
}
|
|
356
397
|
|
|
398
|
+
const runningProcessWarning = (!jsonMode && !backgroundChild) ?
|
|
399
|
+
warnAboutRunningProcesses() :
|
|
400
|
+
Promise.resolve();
|
|
357
401
|
await watcher.start();
|
|
402
|
+
await runningProcessWarning;
|
|
358
403
|
} catch (err) {
|
|
359
404
|
cleanupShutdownHandlers();
|
|
360
405
|
if (jsonMode) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-tank",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "Monitor and query usage limits for LLM CLI tools (Claude,
|
|
3
|
+
"version": "0.9.8",
|
|
4
|
+
"description": "Monitor and query usage limits for LLM CLI tools (Claude, Antigravity, Codex) via HTTP API",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"agent-tank": "bin/agent-tank.js"
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"keywords": [
|
|
20
20
|
"llm",
|
|
21
21
|
"claude",
|
|
22
|
-
"
|
|
22
|
+
"antigravity",
|
|
23
|
+
"agy",
|
|
23
24
|
"codex",
|
|
24
25
|
"openai",
|
|
25
26
|
"anthropic",
|
|
@@ -42,6 +43,7 @@
|
|
|
42
43
|
},
|
|
43
44
|
"homepage": "https://agenttank.io",
|
|
44
45
|
"dependencies": {
|
|
46
|
+
"chokidar": "^3.6.0",
|
|
45
47
|
"node-pty": "^1.0.0",
|
|
46
48
|
"source-map-support": "^0.5.21"
|
|
47
49
|
},
|
package/src/activity-monitor.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ActivityMonitor - Monitors local log directories for LLM CLI activity
|
|
3
3
|
*
|
|
4
|
-
* Watches known log directories for Claude, Codex, and
|
|
4
|
+
* Watches known log directories for Claude, Codex, and Antigravity using chokidar with polling.
|
|
5
5
|
* When activity is detected (new log entries), it triggers usage refresh callbacks
|
|
6
6
|
* with configurable debouncing to prevent excessive polling.
|
|
7
7
|
*/
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
const fs = require('node:fs');
|
|
10
10
|
const path = require('node:path');
|
|
11
11
|
const os = require('node:os');
|
|
12
|
+
const chokidar = require('chokidar');
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Default log directories for each agent.
|
|
@@ -23,9 +24,8 @@ const DEFAULT_LOG_DIRECTORIES = {
|
|
|
23
24
|
path.join(os.homedir(), '.codex', 'sessions'),
|
|
24
25
|
path.join(os.homedir(), '.codex'),
|
|
25
26
|
],
|
|
26
|
-
|
|
27
|
-
path.join(os.homedir(), '.
|
|
28
|
-
path.join(os.homedir(), '.gemini'),
|
|
27
|
+
agy: [
|
|
28
|
+
path.join(os.homedir(), '.gemini', 'antigravity-cli'),
|
|
29
29
|
],
|
|
30
30
|
};
|
|
31
31
|
|
|
@@ -72,7 +72,7 @@ class ActivityMonitor {
|
|
|
72
72
|
|
|
73
73
|
/**
|
|
74
74
|
* Start monitoring log directories for activity.
|
|
75
|
-
* Sets up
|
|
75
|
+
* Sets up chokidar polling watchers on each agent's log directories.
|
|
76
76
|
*
|
|
77
77
|
* @returns {Object} Status object with monitoring details
|
|
78
78
|
*/
|
|
@@ -92,7 +92,18 @@ class ActivityMonitor {
|
|
|
92
92
|
for (const dir of dirs) {
|
|
93
93
|
if (fs.existsSync(dir)) {
|
|
94
94
|
try {
|
|
95
|
-
|
|
95
|
+
// Use chokidar with polling to avoid EMFILE errors from too many native watchers
|
|
96
|
+
const watcher = chokidar.watch(dir, {
|
|
97
|
+
persistent: true,
|
|
98
|
+
ignoreInitial: true,
|
|
99
|
+
usePolling: true,
|
|
100
|
+
interval: 1000,
|
|
101
|
+
depth: 99,
|
|
102
|
+
ignored: ['**/.git/**', '**/*.lock'],
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
watcher.on('all', (eventType, filepath) => {
|
|
106
|
+
const filename = path.relative(dir, filepath);
|
|
96
107
|
this._handleFileChange(agent, eventType, filename);
|
|
97
108
|
});
|
|
98
109
|
|
|
@@ -158,7 +169,7 @@ class ActivityMonitor {
|
|
|
158
169
|
}
|
|
159
170
|
|
|
160
171
|
/**
|
|
161
|
-
* Handle a file change event from
|
|
172
|
+
* Handle a file change event from chokidar.
|
|
162
173
|
* Debounces activity detection per agent.
|
|
163
174
|
*
|
|
164
175
|
* @param {string} agent - Agent name
|