omniagent 0.1.7 → 0.1.9

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 CHANGED
@@ -71,11 +71,33 @@ npx omniagent@latest sync --list-local
71
71
  # Apply a sync profile (see docs/profiles.md)
72
72
  npx omniagent@latest sync --profile code-reviewer
73
73
 
74
+ # Show usage limits for installed usage-capable agents
75
+ omniagent usage
76
+ omniagent usage codex
77
+ omniagent usage --only claude,codex
78
+ omniagent usage --window=weekly
79
+ omniagent usage --sort=reset
80
+ omniagent usage --sort=left
81
+ omniagent usage codex --window=5h
82
+ omniagent usage --timeout=45
83
+ omniagent usage --agentsDir ./my-custom-agents
84
+ omniagent usage codex --json
85
+ omniagent usage codex --debug
86
+
74
87
  # Shim mode (no subcommand)
75
88
  omniagent --agent codex
76
89
  omniagent -p "Summarize this repo" --agent codex --output json
77
90
  ```
78
91
 
92
+ `usage` supports Codex, Claude, and Gemini in v1. Copilot is not supported for usage
93
+ extraction yet. Usage extraction may launch agent TUIs and may incur cost if an agent
94
+ reads repo context or instructions on startup; omniagent uses cheap/minimal launch settings
95
+ where possible. Usage extraction times out after 30 seconds unless the target config defines
96
+ a target-specific timeout; built-in TUI probes may use longer defaults. Some CLIs require
97
+ session-scoped setup flags to inspect usage, such as Gemini's `--skip-trust`; omniagent does
98
+ not complete auth or onboarding prompts for you. Pass `--timeout=<seconds>` to override the
99
+ per-agent timeout for the current run.
100
+
79
101
  ## Local Overrides (`.local`)
80
102
 
81
103
  Use `.local` files for personal variants that should not become team defaults.
@@ -0,0 +1,146 @@
1
+ import { c as cleanControlOutput, a as compactLines, p as parsePercentUsed, m as makeUsageLimit } from "./cli.js";
2
+ import { r as runPtyScenario, e as enterKey, a as escapeKey } from "./pty-CZBSAJzE.js";
3
+ async function extractClaudeUsage(context) {
4
+ const command = context.command ?? context.launch?.command ?? "claude";
5
+ const model = context.launch?.cheapModel ?? "haiku";
6
+ validateClaudeModel(model);
7
+ const ptyResult = await runPtyScenario({
8
+ command,
9
+ args: context.launch?.args ?? ["--model", model],
10
+ cwd: context.repoRoot,
11
+ cols: 100,
12
+ rows: 40,
13
+ timeoutMs: context.launch?.timeoutMs ?? 6e4,
14
+ signal: context.signal,
15
+ debug: context.debug,
16
+ steps: [
17
+ { waitFor: /Claude|>|❯/u, waitForSource: "screen", waitForTimeoutMs: 4e3 },
18
+ { write: enterKey() },
19
+ { waitFor: /Claude|>|❯/u, waitForSource: "screen", waitForTimeoutMs: 8e3 },
20
+ { write: `/usage${enterKey()}` },
21
+ {
22
+ waitFor: hasClaudeUsageRows,
23
+ waitForTimeoutMs: 15e3,
24
+ capture: "usage",
25
+ captureWaitMs: 500
26
+ },
27
+ { write: escapeKey() },
28
+ { waitMs: 500 },
29
+ { write: `/exit${enterKey()}` }
30
+ ]
31
+ });
32
+ const usageSnapshot = ptyResult.snapshots.usage ?? ptyResult;
33
+ const cleanedOutput = cleanControlOutput(usageSnapshot.raw);
34
+ const parsed = parseClaudeUsage(usageSnapshot.screen, cleanedOutput);
35
+ const limits = buildClaudeUsageLimits(parsed, context);
36
+ if (limits.length === 0) {
37
+ throw new Error("Claude usage output did not include session or weekly usage rows.");
38
+ }
39
+ return {
40
+ targetId: context.targetId,
41
+ displayName: context.displayName,
42
+ command,
43
+ limits,
44
+ debug: ptyResult.debug.length > 0 ? ptyResult.debug : void 0
45
+ };
46
+ }
47
+ function hasClaudeUsageRows(snapshot) {
48
+ const parsed = parseClaudeUsage(snapshot.screen, cleanControlOutput(snapshot.raw));
49
+ return Boolean(parsed.currentSessionUsed || parsed.currentWeekUsed);
50
+ }
51
+ function buildClaudeUsageLimits(parsed, context) {
52
+ const sessionUsed = parsePercentUsed(parsed.currentSessionUsed);
53
+ const weekUsed = parsePercentUsed(parsed.currentWeekUsed);
54
+ const limits = [];
55
+ if (parsed.currentSessionUsed.trim()) {
56
+ limits.push(
57
+ makeUsageLimit({
58
+ targetId: context.targetId,
59
+ scope: "current_session",
60
+ window: "session",
61
+ percentUsed: sessionUsed,
62
+ percentRemaining: sessionUsed == null ? null : 100 - sessionUsed,
63
+ resetText: parsed.currentSessionResets,
64
+ raw: formatRaw(parsed.currentSessionUsed, parsed.currentSessionResets),
65
+ now: context.now
66
+ })
67
+ );
68
+ }
69
+ if (parsed.currentWeekUsed.trim()) {
70
+ limits.push(
71
+ makeUsageLimit({
72
+ targetId: context.targetId,
73
+ scope: "current_week",
74
+ window: "weekly",
75
+ percentUsed: weekUsed,
76
+ percentRemaining: weekUsed == null ? null : 100 - weekUsed,
77
+ resetText: parsed.currentWeekResets,
78
+ raw: formatRaw(parsed.currentWeekUsed, parsed.currentWeekResets),
79
+ now: context.now
80
+ })
81
+ );
82
+ }
83
+ return limits;
84
+ }
85
+ function parseClaudeUsage(screen, cleanedOutput = "") {
86
+ const fromScreen = parseClaudeLines(compactLines(screen));
87
+ if (fromScreen.currentSessionUsed || fromScreen.currentWeekUsed) {
88
+ return fromScreen;
89
+ }
90
+ return parseClaudeLines(compactLines(cleanedOutput));
91
+ }
92
+ function parseClaudeLines(lines) {
93
+ const values = {
94
+ currentSessionUsed: "",
95
+ currentSessionResets: "",
96
+ currentWeekUsed: "",
97
+ currentWeekResets: ""
98
+ };
99
+ let section = "";
100
+ for (const line of lines) {
101
+ if (line === "Current session") {
102
+ section = "currentSession";
103
+ continue;
104
+ }
105
+ if (line.startsWith("Current week")) {
106
+ section = "currentWeek";
107
+ continue;
108
+ }
109
+ if (!section) {
110
+ continue;
111
+ }
112
+ const usedMatch = /(\d+(?:\.\d+)?% used)/i.exec(line);
113
+ if (usedMatch != null) {
114
+ if (section === "currentSession") {
115
+ values.currentSessionUsed = usedMatch[1];
116
+ } else {
117
+ values.currentWeekUsed = usedMatch[1];
118
+ }
119
+ continue;
120
+ }
121
+ if (line.startsWith("Resets ")) {
122
+ if (section === "currentSession") {
123
+ values.currentSessionResets = line.slice("Resets ".length).trim();
124
+ } else {
125
+ values.currentWeekResets = line.slice("Resets ".length).trim();
126
+ }
127
+ }
128
+ }
129
+ return values;
130
+ }
131
+ function formatRaw(used, resets) {
132
+ if (!used) {
133
+ return "";
134
+ }
135
+ return resets ? `${used} (resets ${resets})` : used;
136
+ }
137
+ function validateClaudeModel(model) {
138
+ if (!/^[A-Za-z0-9._:-]+$/.test(model)) {
139
+ throw new Error(`Unsupported Claude usage model value: ${model}`);
140
+ }
141
+ }
142
+ export {
143
+ buildClaudeUsageLimits,
144
+ extractClaudeUsage,
145
+ parseClaudeUsage
146
+ };