agy-statusblocks 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +78 -2
- package/dist/cache.d.ts +9 -0
- package/dist/cache.js +65 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +251 -0
- package/dist/colors.d.ts +24 -0
- package/dist/colors.js +42 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +23 -0
- package/dist/credentials.d.ts +1 -0
- package/dist/credentials.js +44 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +158 -0
- package/dist/layout.d.ts +3 -0
- package/dist/layout.js +146 -0
- package/dist/remote-usage-fetch.d.ts +2 -0
- package/dist/remote-usage-fetch.js +22 -0
- package/dist/remote-usage.d.ts +14 -0
- package/dist/remote-usage.js +93 -0
- package/dist/segments/context.d.ts +2 -0
- package/dist/segments/context.js +30 -0
- package/dist/segments/git.d.ts +2 -0
- package/dist/segments/git.js +95 -0
- package/dist/segments/model.d.ts +2 -0
- package/dist/segments/model.js +96 -0
- package/dist/segments/state.d.ts +2 -0
- package/dist/segments/state.js +35 -0
- package/dist/segments/usage.d.ts +2 -0
- package/dist/segments/usage.js +193 -0
- package/dist/spawn.d.ts +1 -0
- package/dist/spawn.js +13 -0
- package/dist/types.d.ts +83 -0
- package/dist/types.js +1 -0
- package/dist/update-check.d.ts +1 -0
- package/dist/update-check.js +33 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +15 -0
- package/package.json +54 -4
- package/postinstall.cjs +17 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { color, c, visibleLength } from '../colors.js';
|
|
2
|
+
const STATE_CONFIG = {
|
|
3
|
+
idle: { label: '● IDLE', color: c.green },
|
|
4
|
+
working: { label: '● RUNNING', color: c.geminiCyan },
|
|
5
|
+
tool_use: { label: '● TOOL USE', color: c.yellow },
|
|
6
|
+
reviewing: { label: '● REVIEW', color: c.purple },
|
|
7
|
+
error: { label: '● ERROR', color: c.red },
|
|
8
|
+
};
|
|
9
|
+
export const stateSegment = {
|
|
10
|
+
id: 'state',
|
|
11
|
+
priority: 35,
|
|
12
|
+
enabled: (data) => Boolean(data.agent_state || data.task_count || data.artifact_count || data.subagents?.length),
|
|
13
|
+
render(data) {
|
|
14
|
+
const rawState = (data.agent_state || 'idle').toLowerCase();
|
|
15
|
+
const stateCfg = STATE_CONFIG[rawState] || { label: `● ${rawState.toUpperCase()}`, color: c.dim };
|
|
16
|
+
const line1 = color(stateCfg.label, stateCfg.color, c.bold);
|
|
17
|
+
// Line 2: orchestration telemetry
|
|
18
|
+
const counters = [];
|
|
19
|
+
if (data.task_count != null && data.task_count > 0) {
|
|
20
|
+
counters.push(`${data.task_count} task${data.task_count === 1 ? '' : 's'}`);
|
|
21
|
+
}
|
|
22
|
+
if (data.subagents && data.subagents.length > 0) {
|
|
23
|
+
counters.push(`${data.subagents.length} subagent${data.subagents.length === 1 ? '' : 's'}`);
|
|
24
|
+
}
|
|
25
|
+
if (data.artifact_count != null && data.artifact_count > 0) {
|
|
26
|
+
counters.push(`${data.artifact_count} artifact${data.artifact_count === 1 ? '' : 's'}`);
|
|
27
|
+
}
|
|
28
|
+
const line2 = counters.length > 0
|
|
29
|
+
? color(counters.join(' · '), c.dim)
|
|
30
|
+
: color('orchestration idle', c.dim);
|
|
31
|
+
const lines = [line1, line2];
|
|
32
|
+
const width = Math.max(...lines.map(visibleLength));
|
|
33
|
+
return { id: 'state', priority: 35, width, lines };
|
|
34
|
+
},
|
|
35
|
+
};
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { color, c, visibleLength, padRight, pctColor, renderBar } from '../colors.js';
|
|
2
|
+
import { readRemoteLimits } from '../remote-usage.js';
|
|
3
|
+
const MS_PER_DAY = 86400000;
|
|
4
|
+
const MS_PER_HOUR = 3600000;
|
|
5
|
+
const MS_PER_MIN = 60000;
|
|
6
|
+
function formatResetTime(epochSec) {
|
|
7
|
+
if (!epochSec)
|
|
8
|
+
return '';
|
|
9
|
+
const ms = epochSec * 1000 - Date.now();
|
|
10
|
+
if (ms <= 0)
|
|
11
|
+
return 'now';
|
|
12
|
+
const d = Math.floor(ms / MS_PER_DAY);
|
|
13
|
+
const h = Math.floor((ms % MS_PER_DAY) / MS_PER_HOUR);
|
|
14
|
+
const m = Math.floor((ms % MS_PER_HOUR) / MS_PER_MIN);
|
|
15
|
+
if (d > 0)
|
|
16
|
+
return `${d}d${h > 0 ? `${h}h` : ''}${m > 0 ? `${m}m` : ''}`;
|
|
17
|
+
if (h > 0)
|
|
18
|
+
return `${h}h${m > 0 ? `${m}m` : ''}`;
|
|
19
|
+
return `${m}m`;
|
|
20
|
+
}
|
|
21
|
+
function clampPercent(v) {
|
|
22
|
+
return Math.min(999, Math.max(0, Math.round(v ?? 0)));
|
|
23
|
+
}
|
|
24
|
+
function parseResetTime(v) {
|
|
25
|
+
if (typeof v === 'number' && Number.isFinite(v)) {
|
|
26
|
+
return v > 1e11 ? Math.floor(v / 1000) : v;
|
|
27
|
+
}
|
|
28
|
+
if (typeof v === 'string') {
|
|
29
|
+
const ms = Date.parse(v);
|
|
30
|
+
if (Number.isFinite(ms))
|
|
31
|
+
return Math.floor(ms / 1000);
|
|
32
|
+
}
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
function inferWindowSuffix(resetSec) {
|
|
36
|
+
if (!resetSec || resetSec <= 0)
|
|
37
|
+
return '';
|
|
38
|
+
if (resetSec > 18 * 3600)
|
|
39
|
+
return '7d';
|
|
40
|
+
return '5h';
|
|
41
|
+
}
|
|
42
|
+
function shortenBucketLabel(rawKey, resetSec = 0) {
|
|
43
|
+
const k = rawKey.trim();
|
|
44
|
+
const lower = k.toLowerCase();
|
|
45
|
+
const explicitWin = lower.includes('weekly') || lower.includes('7d') || lower.includes('7-day')
|
|
46
|
+
? '7d'
|
|
47
|
+
: lower.includes('5h') || lower.includes('5-hour')
|
|
48
|
+
? '5h'
|
|
49
|
+
: inferWindowSuffix(resetSec);
|
|
50
|
+
if (lower.includes('claude') && (lower.includes('gpt') || lower.includes('pool') || (!lower.includes('sonnet') && !lower.includes('opus') && !lower.includes('haiku')))) {
|
|
51
|
+
return explicitWin ? `claude ${explicitWin}` : 'claude';
|
|
52
|
+
}
|
|
53
|
+
if (lower.includes('sonnet')) {
|
|
54
|
+
const ver = k.match(/\d+(?:\.\d+)?/)?.[0] ?? '';
|
|
55
|
+
return ver ? `sonnet ${ver}` : 'sonnet';
|
|
56
|
+
}
|
|
57
|
+
if (lower.includes('opus')) {
|
|
58
|
+
const ver = k.match(/\d+(?:\.\d+)?/)?.[0] ?? '';
|
|
59
|
+
return ver ? `opus ${ver}` : 'opus';
|
|
60
|
+
}
|
|
61
|
+
if (lower.includes('haiku')) {
|
|
62
|
+
const ver = k.match(/\d+(?:\.\d+)?/)?.[0] ?? '';
|
|
63
|
+
return ver ? `haiku ${ver}` : 'haiku';
|
|
64
|
+
}
|
|
65
|
+
if (lower.includes('flash'))
|
|
66
|
+
return explicitWin === '7d' ? 'flash 7d' : 'flash';
|
|
67
|
+
if (lower.includes('argon'))
|
|
68
|
+
return 'argon';
|
|
69
|
+
if (lower.includes('pro'))
|
|
70
|
+
return explicitWin === '7d' ? 'pro 7d' : 'pro';
|
|
71
|
+
if (lower.includes('gemini'))
|
|
72
|
+
return explicitWin ? `gemini ${explicitWin}` : 'gemini';
|
|
73
|
+
const cleaned = k.replace(/\s*\(.*?\)\s*/g, '').replace(/^gemini\s+/i, '').replace(/^claude\s+/i, '').trim();
|
|
74
|
+
return cleaned.length > 12 ? cleaned.slice(0, 12) : (cleaned || k);
|
|
75
|
+
}
|
|
76
|
+
function bucketPool(key) {
|
|
77
|
+
const k = key.toLowerCase();
|
|
78
|
+
if (k.includes('claude') || k.includes('sonnet') || k.includes('opus') || k.includes('haiku') || k.includes('gpt'))
|
|
79
|
+
return 'claude';
|
|
80
|
+
if (k.includes('argon'))
|
|
81
|
+
return 'argon';
|
|
82
|
+
if (k.includes('gemini') || k.includes('flash') || k.includes('pro'))
|
|
83
|
+
return 'gemini';
|
|
84
|
+
return 'other';
|
|
85
|
+
}
|
|
86
|
+
function isActiveModelBucket(key, data) {
|
|
87
|
+
const k = key.toLowerCase();
|
|
88
|
+
const mName = (data.model?.display_name ?? '').toLowerCase();
|
|
89
|
+
const mId = (data.model?.id ?? '').toLowerCase();
|
|
90
|
+
if (k && (mName.includes(k) || mId.includes(k)))
|
|
91
|
+
return true;
|
|
92
|
+
for (const token of ['sonnet', 'opus', 'haiku', 'flash', 'argon', 'pro']) {
|
|
93
|
+
if (k.includes(token) && (mName.includes(token) || mId.includes(token)))
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
// If active model is Sonnet/Opus and bucket is a shared Claude/GPT pool
|
|
97
|
+
if ((mName.includes('claude') || mName.includes('sonnet') || mName.includes('opus')) && bucketPool(key) === 'claude') {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
function extractLimits(data) {
|
|
103
|
+
const out = [];
|
|
104
|
+
// 1. Quota map if provided natively by Antigravity (includes Gemini + Argon + Claude/GPT pools)
|
|
105
|
+
if (data.quota && typeof data.quota === 'object') {
|
|
106
|
+
const entries = Object.entries(data.quota)
|
|
107
|
+
.filter(([, bucket]) => bucket && typeof bucket === 'object' && !bucket.disabled);
|
|
108
|
+
// Sort active model's bucket first, then prefer showing distinct pools (Gemini/Argon + Claude), then by highest utilization
|
|
109
|
+
entries.sort(([keyA, a], [keyB, b]) => {
|
|
110
|
+
const actA = isActiveModelBucket(keyA, data) ? 1 : 0;
|
|
111
|
+
const actB = isActiveModelBucket(keyB, data) ? 1 : 0;
|
|
112
|
+
if (actA !== actB)
|
|
113
|
+
return actB - actA;
|
|
114
|
+
const pctA = typeof a.remaining_fraction === 'number' ? (1 - a.remaining_fraction) * 100 : (a.used_percentage ?? 0);
|
|
115
|
+
const pctB = typeof b.remaining_fraction === 'number' ? (1 - b.remaining_fraction) * 100 : (b.used_percentage ?? 0);
|
|
116
|
+
return pctB - pctA;
|
|
117
|
+
});
|
|
118
|
+
const seenLabels = new Set();
|
|
119
|
+
for (const [key, bucket] of entries) {
|
|
120
|
+
const rawPct = typeof bucket.remaining_fraction === 'number'
|
|
121
|
+
? (1 - bucket.remaining_fraction) * 100
|
|
122
|
+
: bucket.used_percentage;
|
|
123
|
+
const pct = clampPercent(rawPct);
|
|
124
|
+
const nowSec = Math.floor(Date.now() / 1000);
|
|
125
|
+
const resetsAt = typeof bucket.reset_in_seconds === 'number' && bucket.reset_in_seconds > 0
|
|
126
|
+
? nowSec + bucket.reset_in_seconds
|
|
127
|
+
: parseResetTime(bucket.reset_time ?? bucket.resets_at);
|
|
128
|
+
const resetSec = resetsAt > nowSec ? resetsAt - nowSec : (bucket.reset_in_seconds ?? 0);
|
|
129
|
+
const label = shortenBucketLabel(key, resetSec);
|
|
130
|
+
if (seenLabels.has(label))
|
|
131
|
+
continue;
|
|
132
|
+
seenLabels.add(label);
|
|
133
|
+
out.push({ label, percent: pct, resetsAt });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// 2. Rate limits if provided
|
|
137
|
+
const rl = data.rate_limits;
|
|
138
|
+
if (rl) {
|
|
139
|
+
if (rl.five_hour) {
|
|
140
|
+
out.push({
|
|
141
|
+
label: '5h',
|
|
142
|
+
percent: clampPercent(rl.five_hour.used_percentage),
|
|
143
|
+
resetsAt: parseResetTime(rl.five_hour.resets_at),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
if (rl.seven_day) {
|
|
147
|
+
out.push({
|
|
148
|
+
label: '7d',
|
|
149
|
+
percent: clampPercent(rl.seven_day.used_percentage),
|
|
150
|
+
resetsAt: parseResetTime(rl.seven_day.resets_at),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
if (rl.daily) {
|
|
154
|
+
out.push({
|
|
155
|
+
label: 'daily',
|
|
156
|
+
percent: clampPercent(rl.daily.used_percentage),
|
|
157
|
+
resetsAt: parseResetTime(rl.daily.resets_at),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// 3. Fallback to cached remote usage
|
|
162
|
+
if (out.length === 0) {
|
|
163
|
+
const remote = readRemoteLimits();
|
|
164
|
+
if (remote && remote.length > 0) {
|
|
165
|
+
const now = Date.now() / 1000;
|
|
166
|
+
return remote.map(l => (l.resetsAt > 0 && l.resetsAt <= now ? { ...l, percent: 0 } : l));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return out;
|
|
170
|
+
}
|
|
171
|
+
export const usageSegment = {
|
|
172
|
+
id: 'usage',
|
|
173
|
+
priority: 25,
|
|
174
|
+
enabled: (data) => extractLimits(data).length > 0,
|
|
175
|
+
render(data) {
|
|
176
|
+
const limits = extractLimits(data);
|
|
177
|
+
if (limits.length === 0) {
|
|
178
|
+
return { id: 'usage', priority: 25, width: 0, lines: [''] };
|
|
179
|
+
}
|
|
180
|
+
const BAR_WIDTH = 8;
|
|
181
|
+
const rows = limits.slice(0, 2).map(l => {
|
|
182
|
+
const bar = renderBar(l.percent, BAR_WIDTH);
|
|
183
|
+
const pctStr = color(`${l.percent}%`, pctColor(l.percent), c.bold);
|
|
184
|
+
const reset = l.resetsAt ? color(`↻ ${formatResetTime(l.resetsAt)}`, c.dim) : '';
|
|
185
|
+
const lbl = color(l.label, c.dim);
|
|
186
|
+
const parts = [bar, pctStr, reset, lbl].filter(Boolean);
|
|
187
|
+
return parts.join(color(' · ', c.dim));
|
|
188
|
+
});
|
|
189
|
+
const width = Math.max(...rows.map(visibleLength));
|
|
190
|
+
const paddedRows = rows.map(r => padRight(r, width));
|
|
191
|
+
return { id: 'usage', priority: 25, width, lines: paddedRows };
|
|
192
|
+
},
|
|
193
|
+
};
|
package/dist/spawn.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function spawnDetached(execPath: string, args: string[]): void;
|
package/dist/spawn.js
ADDED
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export interface AgyQuotaBucket {
|
|
2
|
+
remaining_fraction?: number;
|
|
3
|
+
remaining_amount?: number;
|
|
4
|
+
reset_time?: string;
|
|
5
|
+
reset_in_seconds?: number;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
used_percentage?: number;
|
|
8
|
+
resets_at?: number | string;
|
|
9
|
+
cycle_mode?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface AgyStatusData {
|
|
12
|
+
product?: string;
|
|
13
|
+
conversation_id?: string;
|
|
14
|
+
agent_state?: 'idle' | 'working' | 'tool_use' | 'reviewing' | 'error' | string;
|
|
15
|
+
model: {
|
|
16
|
+
id?: string;
|
|
17
|
+
display_name: string;
|
|
18
|
+
effort?: string;
|
|
19
|
+
};
|
|
20
|
+
context_window: {
|
|
21
|
+
context_window_size: number;
|
|
22
|
+
used_percentage?: number | null;
|
|
23
|
+
remaining_percentage?: number | null;
|
|
24
|
+
total_input_tokens?: number;
|
|
25
|
+
total_output_tokens?: number;
|
|
26
|
+
current_usage?: unknown;
|
|
27
|
+
};
|
|
28
|
+
rate_limits?: {
|
|
29
|
+
five_hour?: {
|
|
30
|
+
used_percentage?: number;
|
|
31
|
+
resets_at?: number | string;
|
|
32
|
+
};
|
|
33
|
+
seven_day?: {
|
|
34
|
+
used_percentage?: number;
|
|
35
|
+
resets_at?: number | string;
|
|
36
|
+
};
|
|
37
|
+
daily?: {
|
|
38
|
+
used_percentage?: number;
|
|
39
|
+
resets_at?: number | string;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
quota?: Record<string, AgyQuotaBucket>;
|
|
43
|
+
current_dir?: string;
|
|
44
|
+
workspace?: {
|
|
45
|
+
current_dir: string;
|
|
46
|
+
project_dir?: string;
|
|
47
|
+
};
|
|
48
|
+
vcs?: {
|
|
49
|
+
type?: string;
|
|
50
|
+
branch?: string;
|
|
51
|
+
dirty?: boolean;
|
|
52
|
+
};
|
|
53
|
+
artifact_count?: number;
|
|
54
|
+
task_count?: number;
|
|
55
|
+
subagents?: unknown[];
|
|
56
|
+
plan_tier?: string;
|
|
57
|
+
terminal_width?: number;
|
|
58
|
+
cost?: {
|
|
59
|
+
total_usd?: number;
|
|
60
|
+
subagent_usd?: number;
|
|
61
|
+
estimated?: number | boolean;
|
|
62
|
+
};
|
|
63
|
+
effort?: {
|
|
64
|
+
level: string;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export interface Block {
|
|
68
|
+
id: string;
|
|
69
|
+
priority: number;
|
|
70
|
+
width: number;
|
|
71
|
+
lines: string[];
|
|
72
|
+
}
|
|
73
|
+
export interface Segment {
|
|
74
|
+
id: string;
|
|
75
|
+
priority: number;
|
|
76
|
+
render(data: AgyStatusData, allocWidth: number): Block;
|
|
77
|
+
enabled(data: AgyStatusData): boolean;
|
|
78
|
+
}
|
|
79
|
+
export interface StatusBlocksConfig {
|
|
80
|
+
segments?: string[];
|
|
81
|
+
stackWithDefault?: boolean;
|
|
82
|
+
remoteUsage?: boolean;
|
|
83
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
|
+
import { isValidVersion, isNewerVersion } from './version.js';
|
|
4
|
+
const REGISTRY_URL = 'https://registry.npmjs.org/agy-statusblocks/latest';
|
|
5
|
+
async function main() {
|
|
6
|
+
let installed = '';
|
|
7
|
+
try {
|
|
8
|
+
installed = readFileSync(new URL('./.version', import.meta.url), 'utf8').trim();
|
|
9
|
+
}
|
|
10
|
+
catch { /* unstamped install */ }
|
|
11
|
+
let latest = '';
|
|
12
|
+
try {
|
|
13
|
+
const res = await fetch(REGISTRY_URL, { signal: AbortSignal.timeout(10000) });
|
|
14
|
+
if (!res.ok)
|
|
15
|
+
return;
|
|
16
|
+
const body = (await res.json());
|
|
17
|
+
if (typeof body.version === 'string')
|
|
18
|
+
latest = body.version.trim();
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (!isValidVersion(latest))
|
|
24
|
+
return;
|
|
25
|
+
if (isValidVersion(installed) && !isNewerVersion(latest, installed))
|
|
26
|
+
return;
|
|
27
|
+
execSync(`npx -y agy-statusblocks@${latest} update`, {
|
|
28
|
+
stdio: 'ignore',
|
|
29
|
+
windowsHide: true,
|
|
30
|
+
timeout: 300000,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
main().catch(() => { });
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const VERSION_RE = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
2
|
+
export function isValidVersion(v) {
|
|
3
|
+
return VERSION_RE.test(v);
|
|
4
|
+
}
|
|
5
|
+
export function isNewerVersion(a, b) {
|
|
6
|
+
if (!isValidVersion(a) || !isValidVersion(b))
|
|
7
|
+
return false;
|
|
8
|
+
const pa = a.split(/[-+]/)[0].split('.').map(Number);
|
|
9
|
+
const pb = b.split(/[-+]/)[0].split('.').map(Number);
|
|
10
|
+
for (let i = 0; i < 3; i++) {
|
|
11
|
+
if (pa[i] !== pb[i])
|
|
12
|
+
return pa[i] > pb[i];
|
|
13
|
+
}
|
|
14
|
+
return false;
|
|
15
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agy-statusblocks",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Opinionated, adaptive block-based status line for Antigravity CLI (agy) with bin-packing layout, rate limit tracking, and live agent telemetry",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"agy-statusblocks": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"!dist/**/*.test.*",
|
|
13
|
+
"postinstall.cjs"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"prepare": "npm run build",
|
|
17
|
+
"postinstall": "node postinstall.cjs",
|
|
18
|
+
"prebuild": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"dev": "tsc --watch",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"preview": "node dist/cli.js preview"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"antigravity",
|
|
26
|
+
"agy",
|
|
27
|
+
"gemini",
|
|
28
|
+
"statusline",
|
|
29
|
+
"status-bar",
|
|
30
|
+
"terminal",
|
|
31
|
+
"cli",
|
|
32
|
+
"ansi",
|
|
33
|
+
"box-drawing",
|
|
34
|
+
"rate-limit",
|
|
35
|
+
"bin-packing",
|
|
36
|
+
"layout"
|
|
37
|
+
],
|
|
38
|
+
"homepage": "https://github.com/okanerturan/agy-statusblocks#readme",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/okanerturan/agy-statusblocks/issues"
|
|
41
|
+
},
|
|
42
|
+
"author": "Okan Turan",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/okanerturan/agy-statusblocks"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=20"
|
|
49
|
+
},
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/node": "^22.0.0",
|
|
53
|
+
"typescript": "^5.7.0",
|
|
54
|
+
"vitest": "^4.1.0"
|
|
55
|
+
}
|
|
56
|
+
}
|
package/postinstall.cjs
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Auto-update ~/.gemini/antigravity-cli/statusblocks/ on npm install/update (if already installed via init)
|
|
2
|
+
const { existsSync } = require('fs');
|
|
3
|
+
const { execFileSync } = require('child_process');
|
|
4
|
+
const { join } = require('path');
|
|
5
|
+
const { homedir } = require('os');
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
const dest = join(homedir(), '.gemini', 'antigravity-cli', 'statusblocks');
|
|
9
|
+
if (existsSync(dest)) {
|
|
10
|
+
execFileSync(process.execPath, [join(__dirname, 'dist', 'cli.js'), 'update'], {
|
|
11
|
+
stdio: 'ignore',
|
|
12
|
+
windowsHide: true,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
} catch {
|
|
16
|
+
// Best-effort — don't fail the install
|
|
17
|
+
}
|