codeclaw 0.2.6 → 0.2.7
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/dist/bot.js +1 -1
- package/dist/code-agent.js +88 -1
- package/package.json +1 -1
package/dist/bot.js
CHANGED
|
@@ -8,7 +8,7 @@ import fs from 'node:fs';
|
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import { execSync, spawn } from 'node:child_process';
|
|
10
10
|
import { doStream, getSessions, getUsage, listAgents, } from './code-agent.js';
|
|
11
|
-
export const VERSION = '0.2.
|
|
11
|
+
export const VERSION = '0.2.7';
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
13
13
|
// Helpers
|
|
14
14
|
// ---------------------------------------------------------------------------
|
package/dist/code-agent.js
CHANGED
|
@@ -728,6 +728,92 @@ function getCodexUsageFromSessions(home) {
|
|
|
728
728
|
}
|
|
729
729
|
return null;
|
|
730
730
|
}
|
|
731
|
+
// ---------------------------------------------------------------------------
|
|
732
|
+
// Claude usage from OAuth API (https://api.anthropic.com/api/oauth/usage)
|
|
733
|
+
// ---------------------------------------------------------------------------
|
|
734
|
+
function getClaudeOAuthToken() {
|
|
735
|
+
try {
|
|
736
|
+
const raw = execSync('security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null', {
|
|
737
|
+
encoding: 'utf-8', timeout: 3000,
|
|
738
|
+
}).trim();
|
|
739
|
+
if (!raw)
|
|
740
|
+
return null;
|
|
741
|
+
const parsed = JSON.parse(raw);
|
|
742
|
+
return parsed?.claudeAiOauth?.accessToken || null;
|
|
743
|
+
}
|
|
744
|
+
catch {
|
|
745
|
+
return null;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
function getClaudeUsageFromOAuth() {
|
|
749
|
+
const token = getClaudeOAuthToken();
|
|
750
|
+
if (!token)
|
|
751
|
+
return null;
|
|
752
|
+
try {
|
|
753
|
+
const raw = execSync(`curl -s --max-time 5 -H "Authorization: Bearer ${token}" -H "anthropic-beta: oauth-2025-04-20" -H "Content-Type: application/json" "https://api.anthropic.com/api/oauth/usage"`, { encoding: 'utf-8', timeout: 8000 }).trim();
|
|
754
|
+
if (!raw || raw[0] !== '{')
|
|
755
|
+
return null;
|
|
756
|
+
const data = JSON.parse(raw);
|
|
757
|
+
const capturedAt = new Date().toISOString();
|
|
758
|
+
const makeWindow = (label, entry) => {
|
|
759
|
+
if (!entry || typeof entry !== 'object')
|
|
760
|
+
return null;
|
|
761
|
+
const usedPercent = roundPercent(entry.utilization);
|
|
762
|
+
if (usedPercent == null)
|
|
763
|
+
return null;
|
|
764
|
+
const remainingPercent = Math.max(0, Math.round((100 - usedPercent) * 10) / 10);
|
|
765
|
+
const resetAt = typeof entry.resets_at === 'string' ? entry.resets_at : null;
|
|
766
|
+
let resetAfterSeconds = null;
|
|
767
|
+
if (resetAt) {
|
|
768
|
+
const resetAtMs = Date.parse(resetAt);
|
|
769
|
+
if (Number.isFinite(resetAtMs)) {
|
|
770
|
+
resetAfterSeconds = Math.max(0, Math.round((resetAtMs - Date.now()) / 1000));
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
return {
|
|
774
|
+
label,
|
|
775
|
+
usedPercent,
|
|
776
|
+
remainingPercent,
|
|
777
|
+
resetAt,
|
|
778
|
+
resetAfterSeconds,
|
|
779
|
+
status: usedPercent >= 100 ? 'limit_reached' : usedPercent >= 80 ? 'warning' : 'allowed',
|
|
780
|
+
};
|
|
781
|
+
};
|
|
782
|
+
const windows = [];
|
|
783
|
+
const w5h = makeWindow('5h', data.five_hour);
|
|
784
|
+
if (w5h)
|
|
785
|
+
windows.push(w5h);
|
|
786
|
+
const w7d = makeWindow('7d', data.seven_day);
|
|
787
|
+
if (w7d)
|
|
788
|
+
windows.push(w7d);
|
|
789
|
+
const w7dOpus = makeWindow('7d Opus', data.seven_day_opus);
|
|
790
|
+
if (w7dOpus)
|
|
791
|
+
windows.push(w7dOpus);
|
|
792
|
+
const w7dSonnet = makeWindow('7d Sonnet', data.seven_day_sonnet);
|
|
793
|
+
if (w7dSonnet)
|
|
794
|
+
windows.push(w7dSonnet);
|
|
795
|
+
const wExtra = makeWindow('Extra', data.extra_usage);
|
|
796
|
+
if (wExtra)
|
|
797
|
+
windows.push(wExtra);
|
|
798
|
+
if (!windows.length)
|
|
799
|
+
return null;
|
|
800
|
+
const overallStatus = windows.some(w => w.status === 'limit_reached') ? 'limit_reached'
|
|
801
|
+
: windows.some(w => w.status === 'warning') ? 'warning'
|
|
802
|
+
: 'allowed';
|
|
803
|
+
return {
|
|
804
|
+
ok: true,
|
|
805
|
+
agent: 'claude',
|
|
806
|
+
source: 'oauth-api',
|
|
807
|
+
capturedAt,
|
|
808
|
+
status: overallStatus,
|
|
809
|
+
windows,
|
|
810
|
+
error: null,
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
catch {
|
|
814
|
+
return null;
|
|
815
|
+
}
|
|
816
|
+
}
|
|
731
817
|
function getClaudeUsageFromTelemetry(home, model) {
|
|
732
818
|
const telemetryRoot = path.join(home, '.claude', 'telemetry');
|
|
733
819
|
if (!fs.existsSync(telemetryRoot))
|
|
@@ -821,6 +907,7 @@ export function getUsage(opts) {
|
|
|
821
907
|
|| getCodexUsageFromSessions(home)
|
|
822
908
|
|| emptyUsage('codex', 'No recent Codex usage data found.');
|
|
823
909
|
}
|
|
824
|
-
return
|
|
910
|
+
return getClaudeUsageFromOAuth()
|
|
911
|
+
|| getClaudeUsageFromTelemetry(home, opts.model)
|
|
825
912
|
|| emptyUsage('claude', 'No recent Claude usage data found.');
|
|
826
913
|
}
|