gitdone-agent 0.6.9 → 0.6.11
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/index.js +60 -4
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -27,7 +27,7 @@ import { randomUUID } from 'node:crypto'
|
|
|
27
27
|
// Reported to the server on every sync so the web UI can flag outdated agents.
|
|
28
28
|
// Keep in lockstep with packages/agent/package.json "version" AND
|
|
29
29
|
// src/lib/agentVersion.ts LATEST_AGENT_VERSION.
|
|
30
|
-
const AGENT_VERSION = '0.6.
|
|
30
|
+
const AGENT_VERSION = '0.6.11'
|
|
31
31
|
|
|
32
32
|
const AGENT_DIR = join(homedir(), '.gitdone-agent')
|
|
33
33
|
const CONFIG_PATH = join(AGENT_DIR, 'config.json')
|
|
@@ -231,9 +231,15 @@ function runDoctor() {
|
|
|
231
231
|
|
|
232
232
|
// ─── Git helpers ─────────────────────────────────────────────────────────────
|
|
233
233
|
|
|
234
|
+
// Room for large command output. `git status --porcelain -uall` (gd-369) lists
|
|
235
|
+
// every untracked file individually, so a repo with a big new/untracked tree can
|
|
236
|
+
// blow past execSync's default 1 MB buffer — which would throw and silently
|
|
237
|
+
// return '' (an EMPTY snapshot, worse than the collapsed view). 64 MB is plenty.
|
|
238
|
+
const GIT_MAX_BUFFER = 64 * 1024 * 1024
|
|
239
|
+
|
|
234
240
|
function git(cmd, cwd) {
|
|
235
241
|
try {
|
|
236
|
-
return execSync(cmd, { cwd, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }).trim()
|
|
242
|
+
return execSync(cmd, { cwd, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], maxBuffer: GIT_MAX_BUFFER }).trim()
|
|
237
243
|
} catch {
|
|
238
244
|
return ''
|
|
239
245
|
}
|
|
@@ -245,7 +251,7 @@ function git(cmd, cwd) {
|
|
|
245
251
|
// (gd-276). Callers decode per-file via decodeDiffText().
|
|
246
252
|
function gitRaw(cmd, cwd) {
|
|
247
253
|
try {
|
|
248
|
-
return execSync(cmd, { cwd, encoding: 'buffer', stdio: ['pipe', 'pipe', 'pipe'] })
|
|
254
|
+
return execSync(cmd, { cwd, encoding: 'buffer', stdio: ['pipe', 'pipe', 'pipe'], maxBuffer: GIT_MAX_BUFFER })
|
|
249
255
|
} catch {
|
|
250
256
|
return Buffer.alloc(0)
|
|
251
257
|
}
|
|
@@ -461,7 +467,10 @@ function parseDiffByFile(diffBuf) {
|
|
|
461
467
|
function getSnapshot(repoPath) {
|
|
462
468
|
const branch = git('git branch --show-current', repoPath) || 'HEAD'
|
|
463
469
|
|
|
464
|
-
|
|
470
|
+
// -uall lists every untracked file individually instead of collapsing a new
|
|
471
|
+
// directory into a single `dir/` entry — so the change list matches what
|
|
472
|
+
// GitHub Desktop shows, file-for-file (gd-369).
|
|
473
|
+
const statusLines = git('git status --porcelain -uall', repoPath).split('\n').filter(Boolean)
|
|
465
474
|
const modified = []
|
|
466
475
|
const staged = []
|
|
467
476
|
const statuses = {}
|
|
@@ -1260,13 +1269,60 @@ async function executeCommand(cfg, cmd, repoPath) {
|
|
|
1260
1269
|
}
|
|
1261
1270
|
|
|
1262
1271
|
// Report discovered repos + machine info, get back which repos to track.
|
|
1272
|
+
// ─── Claude plan usage (gd-355) ────────────────────────────────────────────
|
|
1273
|
+
// Claude Code persists an OAuth token at ~/.claude/.credentials.json and keeps
|
|
1274
|
+
// it fresh. We reuse it to ask Anthropic for the SAME plan-usage numbers the
|
|
1275
|
+
// /usage command shows (account-level: a 5-hour "session" window + a weekly
|
|
1276
|
+
// limit). The АИ Конзола then renders these live. Best-effort: on a missing or
|
|
1277
|
+
// expired token, being offline, or any error we return null and the console
|
|
1278
|
+
// simply keeps the last snapshot. Cached ~60s so the 30s sync loop doesn't hit
|
|
1279
|
+
// the endpoint twice as often as it changes.
|
|
1280
|
+
let usageCache = { at: 0, data: null }
|
|
1281
|
+
async function readClaudeUsage() {
|
|
1282
|
+
const now = Date.now()
|
|
1283
|
+
if (usageCache.data && now - usageCache.at < 60_000) return usageCache.data
|
|
1284
|
+
try {
|
|
1285
|
+
const creds = JSON.parse(readFileSync(join(homedir(), '.claude', '.credentials.json'), 'utf8'))
|
|
1286
|
+
const token = creds?.claudeAiOauth?.accessToken
|
|
1287
|
+
if (!token) return null
|
|
1288
|
+
const ctrl = new AbortController()
|
|
1289
|
+
const to = setTimeout(() => ctrl.abort(), 8000)
|
|
1290
|
+
let res
|
|
1291
|
+
try {
|
|
1292
|
+
res = await fetch('https://api.anthropic.com/api/oauth/usage', {
|
|
1293
|
+
headers: {
|
|
1294
|
+
Authorization: `Bearer ${token}`,
|
|
1295
|
+
'Content-Type': 'application/json',
|
|
1296
|
+
'anthropic-beta': 'oauth-2025-04-20',
|
|
1297
|
+
'User-Agent': 'claude-cli',
|
|
1298
|
+
},
|
|
1299
|
+
signal: ctrl.signal,
|
|
1300
|
+
})
|
|
1301
|
+
} finally { clearTimeout(to) }
|
|
1302
|
+
if (!res.ok) return null // 401 = token expired; Claude Code refreshes it — skip this tick
|
|
1303
|
+
const j = await res.json()
|
|
1304
|
+
const data = {
|
|
1305
|
+
sessionPct: Math.round(j?.five_hour?.utilization ?? 0),
|
|
1306
|
+
sessionResetsAt: j?.five_hour?.resets_at ?? null,
|
|
1307
|
+
weeklyPct: Math.round(j?.seven_day?.utilization ?? 0),
|
|
1308
|
+
weeklyResetsAt: j?.seven_day?.resets_at ?? null,
|
|
1309
|
+
}
|
|
1310
|
+
usageCache = { at: now, data }
|
|
1311
|
+
return data
|
|
1312
|
+
} catch {
|
|
1313
|
+
return null // no creds file / malformed / offline — stay quiet
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1263
1317
|
async function sync(cfg, discovered) {
|
|
1318
|
+
const usage = await readClaudeUsage()
|
|
1264
1319
|
const data = await api(cfg, '/api/v1/agent/sync', {
|
|
1265
1320
|
machineId: cfg.machineId,
|
|
1266
1321
|
hostname: cfg.hostname,
|
|
1267
1322
|
agentVersion: AGENT_VERSION,
|
|
1268
1323
|
roots: cfg.roots,
|
|
1269
1324
|
repos: discovered,
|
|
1325
|
+
...(usage ? { usage } : {}),
|
|
1270
1326
|
})
|
|
1271
1327
|
return data.tracked ?? []
|
|
1272
1328
|
}
|